您的位置:首页 > 其它

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

2012-08-05 09:37 417 查看
模型:求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

;
int dp[1<<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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: