POJ 2686 Traveling by Stagecoach

来源:互联网 发布:c语言成绩管理系统设计 编辑:程序博客网 时间:2024/05/16 17:05

题意:n张票,m个城市,在城市之间有若干条道路相连,从一座城市移动到另一座城市的时间是两座城市间的距离除以车票,求从城市a到城市b的最短时间,如果无法到达城市b则输出impossible

解题思路:状压dp.把状态作为顶点,把状态的转移看成边来建图,状态:现在在城市u,此时还剩下的车票的集合为s,从这个状态出发,使用一张车票i∈s移动到相邻城市v,就相当于转移到了在城市v,此时还剩下的车票的集合为s\{i}这个状态。把这个转移看成一条边,那么边上的花费是(u-v间的距离)/t[i],按照上述方法所构的图可以用dijkstra算法求解。集合s使用状态压缩的方法表示就可以了,由于剩余的车票的集合s随着移动元素个数不断变小,因此这个图实际上是个DAG(有向无环图)。计算DAG的最短路不需要使用dijkstra算法,可以简单的通过dp求解

代码:

#include <iostream>#include <algorithm>#include <string>#include <cstring>#include <cstdio>#include <cmath>using namespace std;#define INF 0x3f3f3f3fconst int maxn=15;const int maxm=35;int t[maxn],d[maxm][maxm];double dp[1<<maxn][maxm];int n,m,p,a,b;void solve_dp(){    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--)    {        for(int u=1;u<=m;u++)        {            for(int i=0;i<n;i++)            {                if(s>>i&1)                {                    for(int v=1;v<=m;v++)                    {                        if(d[u][v]>0)                        {                            dp[s&~(1<<i)][v]=min(dp[s&~(1<<i)][v],dp[s][u]+1.0*d[u][v]/t[i]);                        }                    }                }            }        }    }    for(int s=0;s<(1<<n);s++)    {        res=min(res,dp[s][b]);    }    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)&&n)    {        memset(d,0,sizeof(d));        for(int i=0;i<n;i++)        {            scanf("%d",&t[i]);        }        int f,t,dis;        for(int i=0;i<p;i++)        {            scanf("%d%d%d",&f,&t,&dis);            d[f][t]=d[t][f]=dis;        }        solve_dp();    }    return 0;}/*3 4 3 1 43 1 21 2 102 3 303 4 202 4 4 2 13 12 3 31 3 34 1 24 2 52 4 3 4 15 51 2 102 3 103 4 101 2 0 1 218 5 10 1 52 7 1 8 4 5 6 31 2 52 3 43 4 74 5 31 3 252 4 233 5 221 4 452 5 511 5 990 0 0 0 0*/