状态压缩dp,将n张马票看作n种状态进行状态压缩。
s代表到达剩下的车票集合,v代表现在所在的城市。
d[s][v]表示所需的最小费用。
这样一来,dp[s{i}][u] = min(dp[s{i}[u], dp[s][v] + d[v][u] / t[i])
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 8;
const int maxm = 30;
const int inf = 1234;
int n, m, p, a, b;
int t[maxn+2];
int d[maxm+2][maxm+2];
double dp[1<<maxn][maxm];
double min(double a, double b) {
return a < b ? a : b;
}
int main(int argc, char const *argv[]) {
while (scanf("%d%d%d%d%d", &n, &m, &p, &a, &b) == 5 && n + m + p + a + b) {
a--, b--;
for (int i = 0; i < n; i++) {
scanf("%d", &t[i]);
}
memset(d, -1, sizeof(d));
for (int i = 0; i < p; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
x--, y--;
d[x][y] = d[y][x] = z;
}
for (int i = 0; i < (1 << n); i++) {
fill(dp[i], dp[i] + m, inf);
}
dp[(1<<n)-1][a] = 0;
for (int s = (1 << n) - 1; s >= 0; s--) {
for (int v = 0; v < m; v++) {
for (int i = 0; i < n; i++) {
if (s >> i & 1) {
for (int u = 0; u < m; u++) {
if (d[v][u] >= 0) {
dp[s-(1<<i)][u] = min(dp[s-(1<<i)][u],
dp[s][v] + (double)d[v][u] / t[i]);
}
}
}
}
}
}
double res = inf;
for (int s = (1 << n) - 1; s >= 0; s--) {
res = min(res, dp[s][b]);
}
if (res == inf) {
printf("Impossible\n");
} else {
printf("%.3f\n", res);
}
}
return 0;
}