ZOJ1232 Adventure of Super Mario(DP+SPFA)

dp[u][t]表示从起点出发,到达i点且用了t次magic boot时的最短时间,

方程如下:

dp[v][t]=min(dp[v][t],dp[u][t]+dis[u][v]);

dp[v][t]=min(dp[v][t],dp[u][t-1]) (dis[u][v]<=l)

放进SPFA更新,相当于一个二维的最短路,解决DP在非DAG下的有后效性的问题。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 #define MAXN 111
 7 #define INF (1<<29)
 8 
 9 int n,a,b,m,l,k;
10 int map[MAXN][MAXN],dis[MAXN][MAXN];
11 
12 void Floyd(){
13     memcpy(dis,map,sizeof(map));
14     for(int k=1; k<=a; ++k){
15         for(int i=1; i<=n; ++i){
16             for(int j=1; j<=n; ++j){
17                 if(dis[i][k]==INF || dis[k][j]==INF) continue;
18                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
19             }
20         }
21     }
22 }
23 
24 struct QNode{
25     int u,t;
26     QNode(int _u=0,int _t=0):u(_u),t(_t){}
27 };
28 int dp[MAXN][11];
29 bool vis[MAXN][11];
30 void SPFA(){
31     memset(vis,0,sizeof(vis));
32     vis[n][0]=1;
33     for(int i=1; i<=n; ++i){
34         for(int j=0; j<11; ++j) dp[i][j]=INF;
35     }
36     dp[n][0]=0;
37     queue<QNode> que;
38     que.push(QNode(n,0));
39     while(!que.empty()){
40         int u=que.front().u,t=que.front().t;
41         que.pop();
42         for(int v=1; v<=n; ++v){
43             if(dp[v][t]>dp[u][t]+dis[u][v]){
44                 dp[v][t]=dp[u][t]+dis[u][v];
45                 if(!vis[v][t]){
46                     vis[v][t]=1;
47                     que.push(QNode(v,t));
48                 }
49             }
50         }
51         for(int v=1; t!=k && v<=n; ++v){
52             if(dis[u][v]<=l && dp[v][t+1]>dp[u][t]){
53                 dp[v][t+1]=dp[u][t];
54                 if(!vis[v][t+1]){
55                     vis[v][t+1]=1;
56                     que.push(QNode(v,t+1));
57                 }
58             }
59         }
60         vis[u][t]=0;
61     }
62 }
63 
64 int main(){
65     int t,u,v,w;
66     scanf("%d",&t);
67     while(t--){
68         scanf("%d%d%d%d%d",&a,&b,&m,&l,&k);
69         n=a+b;
70         for(int i=1; i<=n; ++i){
71             for(int j=1; j<=n; ++j) map[i][j]=INF;
72         }
73         while(m--){
74             scanf("%d%d%d",&u,&v,&w);
75             map[u][v]=map[v][u]=min(map[u][v],w);
76         }
77         Floyd();
78         SPFA();
79         int res=INF;
80         for(int i=0; i<=k; ++i){
81             res=min(res,dp[1][i]);
82         }
83         printf("%d
",res);
84     }
85     return 0;
86 }
原文地址:https://www.cnblogs.com/WABoss/p/5090670.html