UVA 10269 Adventure of Super Mario

看了这里 http://blog.csdn.net/acm_cxlove/article/details/8679230的分析之后自己又按照自己的模板写了一遍,算是对spfa又加深了一步认识(以前真是只会用,没想太多)。

又来当一次搬运工,一点点进步。

题意是这样的:A个村庄,B个城堡,共有K次穿越的机会,且不能经过城堡或者穿越距离必须不超过L,否则必须停下来,当然,不能再道路中间停下来。

按照大大的思路是这样做的:对于每出队的一个结点u,均有两种方式继续走下去,一中是使用一次穿越,另一种是不使用。这样对于使用穿越的情况,必须考虑所有满足d[u][v]<=L的点v,然后dp[v][k+1] = min(dp[v][k+1],dp[u][k])转移方程,其中dp[u][k]表示从起点A+B走到u使用k次穿越经过的最小距离;对于不使用穿越的情况就和普通spfa一样转移。

然后怎样判断由一个节点到另一个节点能够满足d[u][v]<=L呢,这中间会涉及到城堡不能穿越,可以求出使用spfa求出(i,j)之间的最短距离,对于j是城堡的时候就不把j入队,这样中间有城堡的两个节点d[i][j]是不能直接穿越的,也就是d[i][j] == inf.

然后下面是我写的代码:

(思路也可以去原po那里看)

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <climits>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <vector>
  8 #include <queue>
  9 #include <algorithm>
 10 #define esp 1e-6
 11 #define pb push_back
 12 #define in  freopen("in.txt", "r", stdin);
 13 #define out freopen("out.txt", "w", stdout);
 14 #define print(a) printf("%d
",(a));
 15 #define bug puts("********))))))");
 16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
 17 #define inf 0x3f3f3f3f
 18 using namespace std;
 19 typedef long long  LL;
 20 typedef vector<int> VI;
 21 typedef vector<int>:: iterator IT;
 22 #define N 2000
 23 #define INF 200000
 24 struct EDGE
 25 {
 26     int i, c;
 27     EDGE *ani,*next;
 28 }   *Edge[N], E[INF];
 29 int d[N][N], inq[N], dp[N][20];
 30 int cnt, A, B, M, L, K;
 31 void add(int i, int j, int c, EDGE &e1, EDGE &e2)
 32 {
 33     e1.i = j, e1.c = c, e1.ani = &e2, e1.next = Edge[i], Edge[i] = &e1;
 34     e2.i = i, e2.c = c, e2.ani = &e1, e2.next = Edge[j], Edge[j] = &e2;
 35     cnt += 2;
 36 }
 37 void init(void)
 38 {
 39     cnt = 0;
 40     memset(Edge, 0, sizeof(Edge));
 41 //    memset(d, 0x0f, sizeof(d));
 42 }
 43 void preprocess(void)
 44 {
 45     memset(d, 0x3f, sizeof(d));
 46     for(int i = 1; i <= A + B; i++)
 47     {
 48         queue<int> q;
 49         memset(inq, 0, sizeof(inq));
 50         inq[i] = 1;
 51         d[i][i] = 0;
 52         q.push(i);
 53         while(!q.empty())
 54         {
 55             int u = q.front();
 56             int v;
 57             q.pop();
 58             inq[u] = 0;
 59             for(EDGE * p = Edge[u]; p; p = p->next)
 60                 if(d[i][v = p->i] > d[i][u] + p->c)
 61                 {
 62                     if(d[i][v] = d[i][u] + p->c, v <= A && !inq[v])
 63                         inq[v] = 1, q.push(v);
 64                 }
 65         }
 66     }
 67 }
 68 void spfa(int s, int end)
 69 {
 70     memset(dp, 0x3f, sizeof(dp));
 71     memset(inq, 0, sizeof(inq));
 72     queue<int> q;
 73     inq[s] = 1;
 74     dp[s][0] = 0;
 75     q.push(s);
 76     while(!q.empty())
 77     {
 78         int u = q.front(), v;
 79         q.pop();
 80         inq[u] = 0;
 81         for(EDGE *p = Edge[u]; p; p = p->next)
 82             for(int k = 0; k <= K; k++)
 83                 if(dp[u][k] < inf)
 84                 {
 85                     if(dp[v = p->i][k] > dp[u][k] + p->c)
 86                         if(dp[v][k] = dp[u][k] + p->c, !inq[v])
 87                             inq[v] = 1, q.push(v);
 88                     if(k - K)
 89                     {
 90                         for(v = 1; v <= A + B; v++)
 91 //                        if(dp[u][k] < inf)
 92                             if(d[u][v] <= L && dp[u][k] < dp[v][k+1])
 93                                 if(dp[v][k+1] = dp[u][k], !inq[v])
 94                                     inq[v] = 1, q.push(v);
 95                     }
 96                 }
 97     }
 98 }
 99 int main(void)
100 {
101 
102     int T;
103     for(int t = scanf("%d", &T); t <= T; t++)
104     {
105         init();
106         scanf("%d%d%d%d%d", &A, &B, &M, &L, &K);
107         for(int i = 1; i <= M; i++)
108         {
109             int u, v, w;
110             scanf("%d%d%d", &u, &v, &w);
111             add(u, v, w, E[cnt], E[cnt + 1]);
112         }
113         preprocess();
114         spfa(A+B, 1);
115         int ans = inf;
116         for(int k = 0; k <= K; k++)
117             ans = min(dp[1][k], ans);
118         printf("%d
", ans);
119     }
120     return 0;
121 }
原文地址:https://www.cnblogs.com/rootial/p/SPFA-DP.html