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;

}

 

你可能感兴趣的:(压缩)