首页 > 代码库 > POJ 3311-Hie with the Pie(最短路+状压DP)

POJ 3311-Hie with the Pie(最短路+状压DP)

题目链接:点击打开链接

题意:大致就是邮递员要从0号 送快件,一共有n个地方,要求从0开始走完所有的节点在回到0的最短路径。先用Floyd跑出来最短路,然后就是一个裸TSP问题了

TSP:顾名思义,旅行商问题,就是从起点出发遍历n个城市在回到起点的最短路径,在n比较小的情况下状压是个比较好的办法,二进制0代表没访问该城市,反之亦然。所以一共有 2^n-1种状态, 设 dp[s][i] 代表当前状态为s 当前所在城市节点为i dp[s][i]=min(dp[s][i] ,dp[s‘][j]+dis[j][i]) (从当前状态中去掉i 然后从其他的已经访问过的节点中更新dp[s][i])

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <vector>
#include <deque>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define maxn 1<<11
#define Mod 1000000007
#define ll long long
#define _ll __int64
#define ull unsigned long long
using namespace std;
int n,dis[15][15],dp[maxn][15];
void Floyd()
{
    for(int k=0; k<=n; k++)
        for(int i=0; i<=n; i++)
            for(int j=0; j<=n; j++)
                dis[i][j]=min(dis[i][j],dis[i][k] +dis[k][j]);
}
void solve()
{
    int tot=(1<<n)-1;
    for(int s=0; s<=tot; s++)
    {
        for(int i=1; i<=n; i++)
        {
            if(s&(1<<(i-1)))
            {
                if(s==(1<<(i-1)))
                    dp[s][i]=dis[0][i];
                else
                {
                    dp[s][i]=INF;
                    for(int j=1; j<=n; j++)
                        if(s&(1<<(j-1)) && j!=i)
                            dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+dis[j][i]);
                }
            }
        }
    }
    int ans=INF;
    for(int i=1; i<=n; i++)
        ans=min(ans,dp[tot][i]+dis[i][0]);
    printf("%d\n",ans);
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0; i<=n; i++)
            for(int j=0; j<=n; j++)
                scanf("%d",&dis[i][j]);
        Floyd();
        solve();
    }
    return 0;
}

POJ 3311-Hie with the Pie(最短路+状压DP)