版权声明:最后一年,加油~ https://blog.csdn.net/zzti_xiaowei/article/details/82593221
思路:
经典的状压dp,写的太少了~
- dp[s][u]表示剩下的车票集合为s并且现在在城市u的状态所需要的最小花费 。
- 现在所在的城市u,剩下的车票集合为s,从这个状态出发,使用一张车票i(i在剩下车票集合s中)移动到城市v,相当于从状态dp[s][u]转移到了状态dp[s\i][v],实现了状态转移!
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int Max_n=10;
const int Max_m=40;
int n,m,p,a,b;
int t[Max_n];
int d[Max_m][Max_m];
double dp[1<<Max_n][Max_m];
int main()
{
while(~scanf("%d%d%d%d%d",&n,&m,&p,&a,&b)&&n+m){
memset(d,0x3f,sizeof(d));
for(int i=(1<<n)-1;i>=0;i--)
fill(dp[i],dp[i]+m+1,inf);
for(int i=0;i<n;i++)scanf("%d",&t[i]);
int x,y,z;
for(int i=0;i<p;i++){
scanf("%d%d%d",&x,&y,&z);
d[x][y]=z;d[y][x]=z;
}
dp[(1<<n)-1][a]=0; //起点状态值为0
for(int s=(1<<n)-1;s>=0;s--){ //dp[s][u]-->dp[s\i][v]
for(int u=1;u<=m;u++){
for(int i=0;i<n;i++){
if(s&(1<<i)){
for(int v=1;v<=m;v++){
if(d[u][v]!=inf)
dp[s&~(1<<i)][v]=min(dp[s&~(1<<i)][v],dp[s][u]+(double)d[u][v]/t[i]);
}
}
}
}
}
double Min=inf;
for(int s=(1<<n)-1;s>=0;s--){
if(dp[s][b]<Min)Min=dp[s][b];
}
if(Min!=inf)printf("%f\n",Min);
else printf("Impossible\n");
}
return 0;
}