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;

 

posted @ 2018-04-17 14:45  qrfkickit  阅读(232)  评论(0编辑  收藏  举报