COJ 1129 送货到家 (状态压缩DP)

模型:求n个城市的最短hamilton回路,n<=15。

分析:看到n<=15这样的条件容易想到状态压缩DP。hamilton回路其实就是n个城市的一个圆排列,任选一个起点最后的结果都一样,我们不妨设结点0为起点,状态设计也就不难了。

状态设计:d[s][last],表示从结点0出发,已经走过的结点构成状态s,最后走的结点为last;

状态转移:d[s][last]=MIN(d[ns][k]+g[k][last]),ns为s中去掉last那一位,k为ns中是1的位(不能是起点0);

边界:当s中只有2位是1的时候,说明从0结点出发,到达last,所以直接返回g[0][last]。

结果:ans=MIN(d[(1<<n)-1][k]+g[0][k]),k=1,2……n-1

说明:这题坑爹的是NoAnswer的情况,题目没说明白,其实邻接矩阵中的0代表INF,说明不连通,就因为这个原因WA到吐血,最后问A了的人才明白。

View Code
#include <stdio.h>
#include <string.h>
#define N 16
#define INF 0x3f3f3f3f
#define MIN(a,b) ((a)<(b)?(a):(b))
int n;
int g[N][N];
int dp[1<<N][N];
int DP(int s,int last)
{
    if(dp[s][last]!=-1) return dp[s][last];

    int ns=s^(1<<last);
    if(ns==1)    return  dp[s][last]=g[0][last];

    int ret=INF;
    for(int i=1;i<n;i++)
    {
        if((ns^(1<<i))<ns)  ret=MIN(ret,DP(ns,i)+g[i][last]);
    }
    return dp[s][last]=ret;
}
int main()
{
    int i,j;
    while(~scanf("%d",&n))
    {
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                scanf("%d",&g[i][j]);
                if(g[i][j]==0 && i^j)   g[i][j]=INF;
            }
        }
        int ans=INF;
        memset(dp,0xff,sizeof(dp));
        for(i=n-1;i;i--)
        {
            ans=MIN(ans,DP((1<<n)-1,i)+g[0][i]);
        }
        if(n==1)    ans=0;
        if(n==2)    ans=2*g[0][1];
        if(ans<INF) printf("%d\n",ans);
        else    puts("NoAnswer");
    }
    return 0;
}

 

posted @ 2012-08-05 09:37  BeatLJ  阅读(273)  评论(0编辑  收藏  举报