POJ 3311 Hie with the Pie(状态压缩DP)

题目链接:POJ 3311 Hie with the Pie

floyd求出任意两点间最短距离,然后枚举所有状态,用dp做,dp[s][i] = min(dp[s][i], dp[s & (~(1 << (i - 1)))][j] + d[j][i]);,dp[s][i]表示在s状态下,以i为终结点的最短距离。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int MAX_N = 10;
const int MAX_S = (1 << 10) + 100;
const int MAX_M = 10 + 2;
const int INF = 0x3f3f3f3f;
int d[MAX_M][MAX_M], dp[MAX_S][MAX_M], n;

void floyd()
{
    for(int k = 0; k < n + 1; k++)
        for(int i = 0; i < n + 1; i++)
            for(int j = 0; j < n + 1; j++)
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
int main()
{
    while(scanf("%d", &n), n)
    {
        memset(dp, INF, sizeof(dp));
        memset(d, INF, sizeof(d));
        int time;
        for(int i = 0; i < n + 1; i++)
        {
            for(int j = 0; j < n + 1; j++)
            {
                scanf("%d", &time);
                d[i][j] = time;
            }
        }
        floyd();
        int S = (1 << n) - 1;
        for(int i = 1; i < n + 1; i++)
            dp[1 << (i - 1)][i] = d[0][i];
        for(int s = 0; s <= S; s++)
            for(int i = 1; i < n + 1; i++)
                if(s & (1 << (i - 1)))
                    for(int j = 1; j < n + 1; j++)
                        if((s & (1 << (j - 1))) && (i != j))
                            dp[s][i] = min(dp[s][i], dp[s & (~(1 << (i - 1)))][j] + d[j][i]);
        int res = INF;
        for(int i = 1; i < n + 1; i++)
            res = min(res, dp[S][i] + d[i][0]);
        printf("%d\n", res);
    }
    return 0;
}


你可能感兴趣的:(POJ 3311 Hie with the Pie(状态压缩DP))