POJ 2686 (状态转移dp)

来源:互联网 发布:echart 数据加载不合并 编辑:程序博客网 时间:2024/05/22 03:32

题意:

有n张车票,m个城市,p条路线,现在要从a到b城市,问如何才能使时间最短,
时间是指: v到u城市的时间是dis[v][u]/t[i]

/**    感悟,对于状态转移dp,思考的时候,妖之道如何建立状态,    如何利用状态,这样才知道怎么写solve()*/#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int INF = 0x3f3f3f3f;const int MAXN = 50;int n,m,p,a,b;double dp[1<<20][MAXN];int dis[MAXN][MAXN];int t[MAXN];void solve(){    for(int i = 0;i < 1<<n; i++)        for(int j = 0;j < m+1; j++)            dp[i][j] = INF;    dp[(1<<n)-1][a-1] = 0;    double ans = INF;    for(int S = (1<<n)-1;S >= 0; S--) {        ans = min(ans,dp[S][b-1]);        /**从v到u,用i的车票*/        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(dis[v][u] >= 0) {                            /**这里需要好好思考*/                            dp[S & ~(1<<i)][u] = min(dp[S & ~(1<<i)][u],dp[S][v] +                                                      (double)dis[v][u]/t[i]);                        }                    }                }            }        }    }    if(ans == INF)        printf("Impossible\n");    else        printf("%.3f\n",ans);}int main(){    //freopen("in.txt","r",stdin);    while(scanf("%d%d%d%d%d",&n,&m,&p,&a,&b) != EOF) {        if(n + m + p + a + b == 0)            break;        for(int i = 0;i < n; i++)            scanf("%d",&t[i]);        memset(dis,-1,sizeof(dis));        for(int i = 0;i < p; i++) {            int x,y,z;            scanf("%d%d%d",&x,&y,&z);            x--,y--;            dis[x][y] = dis[y][x] = z;        }        solve();    }    return 0;}
0 0
原创粉丝点击