Traveling by Stagecoach(POJ-2686)(状态压缩DP)

来源:互联网 发布:宣传册制作软件 编辑:程序博客网 时间:2024/05/20 05:12

状态压缩DP和普通DP唯一的区别就是它所枚举的对象不再是一个整数,而是一个集合,解决的策略就是利用二进制将这个集合压缩成一个整数。

对于该题,dp[s][v]表示:s表示在该城市剩下的车票集合,v表示在城市v,dp表示在该状态的最小话费。

影响决策的因素有一下几个:

1.一共使用哪几个车票(包括数量和种类)

2.当前从哪个城市到哪个城市

3.使用哪个车票完成两个城市的转移

所以一共需要枚举4个量,用4重循环完成状态转移。

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int max_n = 15;const int max_m = 35;const int INF = 1000000;int n,m,p,a,b,t[max_n],d[max_m][max_m];double dp[1 << max_n][max_m];void solve() {    for(int i=0;i<1<<n;i++){        fill(dp[i],dp[i]+m,INF);    }    dp[(1<<n) - 1][a-1] = 0;    double res = INF;//用二进制位保存集合,1表示有票,0表示没票    for(int s=(1<<n)-1;s>=0;s--){ //枚举使用的车票个数, 不一定车票都用才好        res = min(res,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(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("%.3f\n",res);}int main() {    while(~scanf("%d%d%d%d%d",&n,&m,&p,&a,&b)){        if(!n&&!m&&!p&&!a&&!b) return 0;        memset(d,-1,sizeof(d));        for(int i=0;i<n;i++) scanf("%d",&t[i]);        for(int i=0;i<p;i++) {            int q,w,e;            scanf("%d%d%d",&q,&w,&e);            q--; w--;            d[q][w] = d[w][q] = e;        }        solve();    }    return 0;}


0 0