大致题意
有m座城市,城市间有p条道路,商人持有n张车票,(张车票对应相应的马匹数为 ti),需要从城市a前往城市b。两个直接相连城市花费时间为道路长度除以车票对应马匹数。求所需最小时间,不可达输出"Impossible"。1<=n<=8, 2<=m<=30。
考虑 “现在所余车票集合S,目前位于城市v” 的状态,n范围较小,S使用状态压缩方法表示。记忆化搜索求解。
#include <cstdio>
#include <STDLIB.H>
#include <cmath>
#include <iostream>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define abs(x) ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define eps 1e-4
#define M_PI 3.14159265358979323846
#define MAX_M 30
#define MAX_N 8
using namespace std;
int N, M, P, A, B;
int T[MAX_N], cost[MAX_M][MAX_M];
double dp[1 << MAX_N][MAX_M];
void init(){
--A, --B;
for(int i = 0; i < N; i++) scanf("%d", T + i);
memset(cost, -1, sizeof(cost));
for(int i = 0; i < P; i++){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
--x, --y;
cost[x][y] = z, cost[y][x] = z;
}
}
double rec(int S, int v){
if(dp[S][v] > -1) return dp[S][v];
if(v == B) return dp[S][v] = 0.0;
double res = INF;
for(int u = 0; u < M; u++){
if(cost[v][u] == -1) continue;
for(int t = 0; t < N; t++){
if(!(S >> t & 1)){
int next = S | 1 << t;
if(next == (1 << MAX_N) - 1 && u != B) continue;
res = min(res, rec(next, u) + (double)cost[v][u] / T[t]);
}
}
}
return dp[S][v] = res;
}
void solve(){
for(int i = 0; i < 1 << MAX_N; i++){
for(int j = 0; j < MAX_M; j++) dp[i][j] = -1;
}
double res = min(INF, rec(0, A));
if(res == INF) printf("Impossible\n");
else printf("%.3f\n", res);
}
int main(){
while(~scanf("%d%d%d%d%d", &N, &M, &P, &A, &B) && N){
init();
solve();
}
return 0;
}