POJ2686--Travelling by Stagecoach

题目大意:m个城市,p条双向路,n张车票,上面记录着马的数量,从一个城市到另一个城市都需要用车票,时间为,两个城市之间道路的长度除以车票上马的数量。求从城市a到城市b的最短时间,无法到达输出Impossible


分析:状压DP。状态:dp[S][v],表示的是到达城市v,且剩下的车票的集合为S时的最短时间

状态转移方程:dp[S & ~(1<<i)][u] = min(dp[S & ~(1<<i)][u], dp[S][v] + g[v][u]*1.0/t[i]);


代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 1111;
double dp[maxn][35];
int g[35][35];
int t[10];
int n, m, p, a, b;

int main() {
    while(scanf("%d%d%d%d%d", &n, &m, &p, &a, &b) && n != 0 && m != 0) {
        for(int i = 0; i < n; i++)
            scanf("%d", &t[i]);
        for(int i = 0; i < m; i++)
            memset(g[i], -1, sizeof(g[i]));
        for(int i = 0; i < p; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            u--, v--;
            g[u][v] = w;
            g[v][u] = w;
        }
        for(int i = 0; i < 1<<n; i++)
            fill(dp[i], dp[i]+m, 100000000.0);
        dp[(1<<n)-1][a-1] = 0.0;
        double ans = 100000000.0;
        for(int S = (1<<n) -1; S >= 0; S--) {
            ans = min(ans, dp[S][b-1]);
            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(g[v][u] >= 0) {
                                //使用车票i,从城市v到城市u
                                dp[S & ~(1<<i)][u] = min(dp[S & ~(1<<i)][u], dp[S][v] + g[v][u]*1.0/t[i]);
                            }
                        }
                    }
                }
            }
        }
        if(ans != 100000000.0) printf("%.3f\n", ans);
        else printf("Impossible\n");
    }
    return 0;
}


你可能感兴趣的:(POJ2686--Travelling by Stagecoach)