Traveling by Stagecoach (Poj 2686)
原题链接
思路
由于 \(k\) 的范围只有 \(8\), 很容易想到这题要用一个暴力的方法,我们可以用 状压dp 来解决这个问题。
令 \(f[i][j]\) 为 当前车票的可选即可为 \(i\) ,并且 当前的位置是 \(j\) 的最小花费,然后进行状态转移即可
SOLUTION
#include <cstdio>
#include <cstring>
const int N = 10, M = 32, INF = 0x3f3f3f3f;
int a[N];
int g[M][M];
double f[1 << N][M];
int n, m, k;
int s, e;
void chkmin(int &x, int y) {
x = (x <= y ? x : y);
}
void chkmin(double &x, double y) {
x = (x <= y ? x : y);
}
void solve() {
for(int i = 1; i <= k; i ++ ) scanf("%d", a + i);
memset(g, 0x3f, sizeof g);
for(int i = 0; i < m; i ++ ) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
chkmin(g[u][v], w);
chkmin(g[v][u], w);
}
for(int i = 0; i < 1 << k; i ++ ) {
for(int j = 0; j <= n; j ++ ) {
f[i][j] = INF;
}
}
f[(1 << k) - 1][s] = 0;
for(int i = (1 << k) - 1; i > 0; i -- ) {
for(int u = 1; u <= n; u ++ ) if(f[i][u] <= INF / 2) {
for(int v = 1; v <= n; v ++ ) if(u != v && g[u][v] <= INF / 2) {
for(int j = 0; j < k; j ++ ) if(i >> j & 1) {
chkmin(f[i ^ (1 << j)][v], f[i][u] + (double)g[u][v] / a[j + 1]);
// printf("> %.3f\n", f[i ^ (1 << j)][v]);
}
}
}
}
double ans = 1e18;
for(int i = 0; i < 1 << k; i ++ ) chkmin(ans, f[i][e]);
if(ans >= INF / 2) puts("Impossible");
else printf("%.3lf\n", ans);
}
int main() {
while(true) {
scanf("%d%d%d", &k, &n, &m);
scanf("%d%d", &s, &e);
if(!k && !n && !m && !s && !e) break;
solve();
}
return 0;
}