POJ 2686 Traveling by Stagecoach (dp,状态压缩)


 

题意:旅行家要从城市a旅行到城市b,他的手里有n张马车票,使用马车票可以让旅行家在任意一条马路上通行,马车票上印有马匹的数量t[i],并规定道路的长度除以马匹的数量就是通行该路所花的时间。那么旅行家从城市a到b至少需要花多少时间,如果无法通行,输出‘Impossible’

思路:状态压缩dp,设集合S为旅行家手里剩余的马车票,dp[S][v]含义:旅行家还剩余的马车票组成集合S,并且已到达城市v的时候所花的时间总和。若目前已到达城市v,且马车票组成的集合为S,此时使用集合S中的第i张马车票到达城市u,那么状态转移过程可以表示为:
dp[S&~(1<<i)][u]=min{dp[S&~(1<<i)][u],dp[s][v]+d[s][v]/t[i]};

状压dp就是状态压缩dp,把选取的状态换成二进制,变成一个整数,这样就是状态压缩。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define mem(x,v) memset(x,v,sizeof(x))
const int INF = 0x3f3f3f3f;
int n,m,p,a,b,x,y,z;
int  d[40][40];
double dp[1 << 10][40];
int t[10];
int main(){
    while(~scanf("%d%d%d%d%d",&n,&m,&p,&a,&b) && n){
        a--; b--;
        for (int i = 0; i < n; i++)
            scanf("%d",&t[i]);
        mem(d,-1);
        for (int i = 0; i < p; i++){
            scanf("%d%d%d",&x,&y,&z);
            d[x-1][y-1] = z;
            d[y-1][x-1] = z;
        }
        for (int i = 0; i < (1 << n); i++)
            fill(dp[i],dp[i]+m+1,INF);
        dp[(1 << n) - 1][a] = 0; //起点,没使用票
        double res = INF;
        for (int s = (1 << n) - 1; s >= 0; s--){
            res = min(res,dp[s][b]);
            for (int v = 0; v < m; v++)
                for (int i = 0; i < n; i++){
                    if ((s >> i) & 1){ //使用 第 i 张票。
                        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]);
                            }
                        }
                    }
                }
        }
        if (res == INF) printf("Impossible\n"); else
            printf("%.3lf\n",res);
    }


    return 0;
}

猜你喜欢

转载自blog.csdn.net/kidsummer/article/details/81239078
今日推荐