题意:有一个旅行家计划乘马车旅行。他所在的国家里共有m个城市,在城市之间有若干道路相连。从某个城市沿着某条道路到相邻的城市需要乘坐马车。而乘坐马车需要使用车票,每用一张车票只可以通过一条道路。每张车票上都记有马的匹数,从一个城市移动到另一个城市的所需时间等于城市之间道路的长度除以马的数量的结果。这位旅行家一共有n张车票,第i张车票上马的匹数是ti。一张车票只能使用一次,并且换乘所需要的时间可以忽略。求从城市a到城市b所需要的最短时间。如果无法到达城市b则输出”Impossible”。
思路:见代码。
注意一点:这里我输入数据是1 to n,所以这就导致了在后面需要-1,如果是0 to n-1的话,就可以正常写了,因为这和位运算操作一一对应
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, p, a, b;
int t[10];
int d[50][52];
double dp[1025][50];
//dp[S][v]表示现在车票集合状态为S,当前位于城市v的时候,所要到达目的地的花费
int main() {
while(~scanf("%d%d%d%d%d", &n, &m, &p, &a, &b)) {
if(n + m + p + a + b == 0) break;
memset(d, -1, sizeof(d));
for(int i = 1; i <= n; i++) scanf("%d", &t[i]);
for(int i = 1; i <= p; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
d[u][v] = w;
d[v][u] = w;
}
for (int i = 0; i < (1 << n); i++)
fill(dp[i], dp[i] + m + 1, inf);
dp[(1 << n) - 1][a] = 0;
for(int s = (1 << n) - 1; s >= 0; s--) {
//车票集合
for(int u = 1; u <= m; u++) {//起点
for(int i = 1; i <= n; i++) {//遍历车票是否存在
if(s & (1 << (i - 1))) { //如果第i张车票存在.因为左移0位相当于判断第1张车票
for(int v = 1; v <= m; v++) { //遍历可由起点到达的点
if(d[u][v] > 0) {
dp[s & ~(1 << (i - 1))][v] = min(dp[s & ~(1 << (i - 1))][v], dp[s][u] + (double)d[u][v] / t[i]);
}
}
}
}
}
}
double res = inf;
for(int i = 0; i < (1 << n) - 1; i++) {
res = min(dp[i][b], res);
}
if (res == inf) printf("Impossible\n");
else printf("%.3f\n", res);
}
return 0;
}