传送门:http://poj.org/problem?id=2686
题意:
一张图有m(m<=100)个点,一个人想从a点乘马车走到b点,他有n(n<=8)张车票,每张车票有一个val为这张车票可以使用的马的数量,马车每到一个地方就要换乘一次,每次换乘会消耗一张车票,消耗当前这条路长度除以车票的val。求走到b点的最短时间。
题解:
看到题目很容易想到这是一道TSP,但是不同于一般TSP,这道题的点数有点大,于是我们不能通过直接表示走过哪些点求解。
这个题还有个关键元素那就是票,票的数量小于等于8,所以我们考虑通过票的使用来进行状态转移。
dp[i][j]表示票的使用为i的状态下最后走到j所需的最小时间。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <vector> 3 #include <cstring> 4 #include <algorithm> 5 #include <cstdio> 6 using namespace std; 7 const int INF=0x3f3f3f3f; 8 typedef long long ll; 9 int n,m,p,a,b,u,v,w,mx,tck[200]; 10 double dp[600][105],ans; 11 struct node { 12 int x,y; 13 node(){} 14 node(int c, int d) {x=c;y=d;} 15 }; 16 vector<node> g[102]; 17 void init() { 18 ans=INF; mx=1<<n; 19 for(int i=0;i<102;++i) g[i].clear(); 20 for(int i=0;i<mx;++i) fill(dp[i],dp[i]+m+1,INF); 21 dp[0][a]=0; 22 } 23 24 int main() { 25 //freopen("in.txt", "r", stdin); 26 while(~scanf("%d%d%d%d%d",&n,&m,&p,&a,&b)) { 27 if(!(n|m|p|a|b)) break; 28 init(); 29 for(int i=1;i<=n;++i) scanf("%d",&tck[i]); 30 for(int i=1;i<=p;++i) { 31 scanf("%d%d%d",&u,&v,&w); 32 g[v].push_back(node(u,w)); g[u].push_back(node(v,w)); 33 } 34 for(int i=0;i<mx;++i) for(int j=1;j<=m;++j) if(dp[i][j]<1e7){ 35 for(int pos=0;pos<g[j].size();++pos)for(int k=1;k<=n;++k)if(~i&(1<<k-1)){ 36 node x=g[j][pos];u=i|(1<<k-1); 37 dp[u][x.x]=min(dp[u][x.x],dp[i][j]+1.0*x.y/tck[k]); 38 if(x.x==b) ans=min(ans,dp[u][x.x]); 39 } 40 } 41 if(ans>1e7) printf("Impossible\n"); 42 else printf("%.5f\n",ans); 43 } 44 return 0; 45 }