poj2686 状态压缩dp

  这个题的意思是给你一个m个顶点, p条边的无向图, 现在想从a走到b, 旅者也带有n张车票, 每张车票上有一定数量的马匹数量, 经过一条边必须使用车票, 且时间花费是边的长度除以马匹数量,问你最少多长时间到达b , 我们可以定义状态dp[s][u]表示从在u点持有s的车票, 那么下面就可以采用刷表法更新最短路, 代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, p, a, b;
int t[20];
int d[50][50];
double dp[1<<10][32];

int main()
{
    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(d, -1, sizeof(d));
        for(int i=0; i<p; i++)
        {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            d[x][y] = d[y][x] = z;
        }
        for(int i=0; i<(1<<(n+1)); i++)
        for(int j=0; j<=m+2; j++) dp[i][j] = inf;
        dp[(1<<n)-1][a] = 0;
        double res = (double)inf;
        for(int s=(1<<n)-1; s>=0; s--)
        {
            for(int u=1; u<=m; u++)
            {
                res = min(res, dp[s][b]);
                for(int i=0; i<n; i++)
                if(((s>>i)&1) == 1)
                for(int v=1; v<=m; v++)
                if(d[u][v]>=0)
                {
                    //printf("u = %d, v = %d\n", u, v);
                    int ns = s&~(1<<i);
                    dp[ns][v] = min(dp[ns][v], dp[s][u]+d[u][v]/(double)t[i]);
                }
            }
        }
        if(res == inf)
        {
            printf("Impossible\n");
        }
        else
            printf("%.5f\n", res);
    }
    return 0;
}

    另外一个版本的代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, p, a, b;
int t[40];
struct edge { int v, cost; };
vector<edge> G[50];
double dp[(1<<10)][32];

int main()
{
    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]);
        for(int i=0; i<=m; i++) G[i].clear();
        for(int i=0; i<p; i++)
        {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            G[x].push_back((edge){y, z});
            G[y].push_back((edge){x, z});
        }
        for(int i=0; i<(1<<(n+1)); i++)
        for(int j=0; j<=m; j++) dp[i][j] = inf;
        double res = inf;
        dp[(1<<n)-1][a] = 0;
        for(int s=(1<<n)-1; s>=0; s--)
        {
            for(int u=1; u<=m; u++) if(dp[s][u] != inf)
            {
                res = min(res, dp[s][b]);
                for(int i=0; i<n; i++) if(((s>>i)&1) == 1)
                {
                    for(int j=0; j<G[u].size(); j++)
                    {
                        int v = G[u][j].v, cost = G[u][j].cost;
                        dp[s&~(1<<i)][v] = min(dp[s&~(1<<i)][v], dp[s][u]+(double)cost/t[i]);
                    }
                }
            }
        }
        if(res == inf)
        {
            printf("Impossible\n");
        }
        else
            printf("%.5f\n", res);
     }
    return 0;
}

 

posted @ 2016-03-07 17:06  xing-xing  阅读(577)  评论(0编辑  收藏  举报