题意是有一个人去旅游,有n张马票,每张上面有ai头马。
给一个有向图,走每条边的费用是长度/马票的马数量,由此可见走到同一个点会有不同的马票,也就是状态不同,需要表示这种多状态只有用状压来解决,
用二进制表示状态后用正常的最短路SPFA跑一遍即可。
#include <queue>
#include<iostream>
#include<stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
using namespace std;
struct ttt{
int p,d;
};
int n;
double dist[1<<8+5][35];//有的票和到的点
double pp[35];
vector<int>map1[35];
double map2[35][35];
int main(){
//freopen("in.txt","r",stdin);
//freopen("output.txt","w",stdout);
int i,j,k,l,t1,t2,t3,m;
int l1,l2,l3,f4,f5;
int sum1;
int s1;
while(scanf("%d %d %d %d %d",&n,&m,&t2,&s1,&t1)==5&&(n||m||t2||s1||t1)){
memset(map1,0,sizeof(map1));
for(i=0;i<=1<<n;i++)
for(j=0;j<=m;j++)
dist[i][j]=1e9+7;
for(i=0;i<n;i++)
cin >> pp[i];
int f1,f2;
double f3;
for(i=1;i<=t2;i++){
cin >> f1>> f2>> f3;
map1[f1].push_back(f2);
map1[f2].push_back(f1);
map2[f1][f2]=f3;
map2[f2][f1]=f3;
}
queue<ttt>qq;
ttt u,v;
u.p=(1<<n)-1; //表示全部票都有
u.d=s1;
qq.push(u);
dist[u.p][u.d]=0;
while(!qq.empty()){
v=qq.front();qq.pop();
for(i=0;i<n;i++){
if(v.p>>i&1){ //有i这个票
for(j=0;j<map1[v.d].size();j++){
int uu=map1[v.d][j]; //vv为距离
if(dist[v.p][v.d]+map2[v.d][uu]/pp[i]<dist[v.p&~(1<<i)][uu]){;
u.p=v.p&~(1<<i); //这张票已经给用掉了
u.d=uu;
dist[u.p][uu]=dist[v.p][v.d]+map2[v.d][uu]/pp[i];
qq.push(u);
}
}
}
}
}
double min1=1e9+7;
for(i=0;i<1<<n;i++)
min1=min(min1,dist[i][t1]);
if(min1!=1e9+7)
printf("%.3f\n",min1);
else
cout << "Impossible"<<endl;
}
return 0;
}