poj2686 状态压缩dp
这个题的意思是给你一个m个顶点, p条边的无向图, 现在想从a走到b, 旅者也带有n张车票, 每张车票上有一定数量的马匹数量, 经过一条边必须使用车票, 且时间花费是边的长度除以马匹数量,问你最少多长时间到达b , 我们可以定义状态dp[s][u]表示从在u点持有s的车票, 那么下面就可以采用刷表法更新最短路, 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int inf = 0x3f3f3f3f; int n, m, p, a, b; int t[20]; int d[50][50]; double dp[1<<10][32]; int main() { while(scanf("%d%d%d%d%d", &n, &m, &p, &a, &b)!=EOF) { if(n+m+p+a+b == 0) break; for(int i=0; i<n; i++) scanf("%d", &t[i]); memset(d, -1, sizeof(d)); for(int i=0; i<p; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); d[x][y] = d[y][x] = z; } for(int i=0; i<(1<<(n+1)); i++) for(int j=0; j<=m+2; j++) dp[i][j] = inf; dp[(1<<n)-1][a] = 0; double res = (double)inf; for(int s=(1<<n)-1; s>=0; s--) { for(int u=1; u<=m; u++) { res = min(res, dp[s][b]); for(int i=0; i<n; i++) if(((s>>i)&1) == 1) for(int v=1; v<=m; v++) if(d[u][v]>=0) { //printf("u = %d, v = %d\n", u, v); int ns = s&~(1<<i); dp[ns][v] = min(dp[ns][v], dp[s][u]+d[u][v]/(double)t[i]); } } } if(res == inf) { printf("Impossible\n"); } else printf("%.5f\n", res); } return 0; }
另外一个版本的代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int inf = 0x3f3f3f3f; int n, m, p, a, b; int t[40]; struct edge { int v, cost; }; vector<edge> G[50]; double dp[(1<<10)][32]; int main() { while(scanf("%d%d%d%d%d", &n, &m, &p, &a, &b) != EOF) { if(n+m+p+a+b == 0) break; for(int i=0; i<n; i++) scanf("%d", &t[i]); for(int i=0; i<=m; i++) G[i].clear(); for(int i=0; i<p; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); G[x].push_back((edge){y, z}); G[y].push_back((edge){x, z}); } for(int i=0; i<(1<<(n+1)); i++) for(int j=0; j<=m; j++) dp[i][j] = inf; double res = inf; dp[(1<<n)-1][a] = 0; for(int s=(1<<n)-1; s>=0; s--) { for(int u=1; u<=m; u++) if(dp[s][u] != inf) { res = min(res, dp[s][b]); for(int i=0; i<n; i++) if(((s>>i)&1) == 1) { for(int j=0; j<G[u].size(); j++) { int v = G[u][j].v, cost = G[u][j].cost; dp[s&~(1<<i)][v] = min(dp[s&~(1<<i)][v], dp[s][u]+(double)cost/t[i]); } } } } if(res == inf) { printf("Impossible\n"); } else printf("%.5f\n", res); } return 0; }