poj 3411 Paid Roads
题意:
n个城市,m条双向路径。
从a城市到b城市,有两种付费方法:
1.在c城市预先付费,前提是已经到达了c城市;
2.到了b城市之后,在b付费。
给出路径以及付费信息,求出从1到n的最少花费,或判断从1无法到达n。
思路:
状态压缩dp,每次更新的时候,更新两次,第一次更新未到达的城市,第二次更新可以通过中转城市话费更少到达的城市。
转移方程:
dp[S|(1<<k)][k] = min(dp[S|(1<<k)][k] ,dp[S][j] + cost[j][k]),其中cost[j][k]要么是提前,要么是到付,判断一下条件即可。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <vector> 5 using namespace std; 6 const int inf = 0x3f3f3f3f; 7 const int N = 12; 8 int dp[(1<<N)][N]; 9 struct node 10 { 11 int a,b,c,p,r; 12 node(int aa,int bb,int cc,int pp,int rr) 13 { 14 a = aa; 15 b = bb; 16 c = cc; 17 p = pp; 18 r = rr; 19 } 20 node(){}; 21 }; 22 vector<node> g[N]; 23 int main() 24 { 25 int n,m; 26 while (scanf("%d%d",&n,&m)!=EOF) 27 { 28 memset(dp,inf,sizeof(dp)); 29 for (int i = 0;i < n;i++) g[i].clear(); 30 for (int i = 0;i < m;i++) 31 { 32 int a,b,c,p,r; 33 scanf("%d%d%d%d%d",&a,&b,&c,&p,&r); 34 a--,b--,c--; 35 g[a].push_back(node(a,b,c,p,r)); 36 } 37 dp[1][0] = 0; 38 for (int i = 0;i < (1<<n);i++) 39 { 40 for (int j = 0;j < n;j++)//第一次 41 { 42 if (!(i&(1<<j))) continue; 43 for (int k = 0;k < g[j].size();k++) 44 { 45 int to = g[j][k].b; 46 int c = g[j][k].c; 47 dp[i|(1<<to)][to] = min(dp[i|(1<<to)][to],dp[i][j] + g[j][k].r); 48 if (i&(1<<c)) dp[i|(1<<to)][to] = min(dp[i|(1<<to)][to],dp[i][j] + g[j][k].p); 49 } 50 } 51 for (int j = 0;j < n;j++)//第二次 52 { 53 if (!(i&(1<<j))) continue; 54 for (int k = 0;k < g[j].size();k++) 55 { 56 int to = g[j][k].b; 57 int c = g[j][k].c; 58 dp[i|(1<<to)][to] = min(dp[i|(1<<to)][to],dp[i][j] + g[j][k].r); 59 if (i&(1<<c)) dp[i|(1<<to)][to] = min(dp[i|(1<<to)][to],dp[i][j] + g[j][k].p); 60 } 61 } 62 } 63 int ans = inf; 64 for (int i = 0;i <(1<<n);i++) ans = min(ans,dp[i][n-1]); 65 if (ans >= inf) puts("impossible"); 66 else printf("%d\n",ans); 67 } 68 return 0;
康复训练中~欢迎交流!