hdu 3001 状态压缩

转载:

http://hi.baidu.com/the_one1989/blog/item/002aeb862327be83f603a618.html

http://acm.hdu.edu.cn/showproblem.php?pid=3001

 

很经典的TSP问题,但是题目又有改变,每个旅游地可以走两遍,故进行扩展2状态的状态压缩DP伸展为3状态的状态压缩问题。0表示没去过此点,1 表示去过一次,2表示去过两次,状态转移方程基本和以前一样dp[i][j]=min(dp[i][k]+map[k][j]),状态压缩表示要稍微耐心 点。

附上代码

#include"iostream"
#include<stdio.h>
#include<memory.h>
#include<climits>
using namespace std;
int dp[60000][10];
int map[10][10];
int num[11]={1,3,9,27,81,243,729,2187,6561,19683,59049};
int ok[60000][10];
int main()
{
    int n,m,i,j,k,s,t,c,now;
    for(i=0;i<num[10];i++){
        now=i;
        for(j=0;j<10;j++)
        {
            ok[i][j]=now%3;
            now/=3;
        }
    }
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(map,-1,sizeof(map));
        memset(dp,-1,sizeof(dp));
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&s,&t,&c);
            if(map[s-1][t-1]==-1||map[s-1][t-1]>c)
            map[s-1][t-1]=map[t-1][s-1]=c;
        }
        for(i=0;i<n;i++)
            map[i][i]=0;
        for(i=0;i<n;i++){
            dp[num[i]][i]=0;
        }
        int min=INT_MAX;
        bool flag;
        for(i=0;i<num[n];i++)
            for(j=0;j<n;j++)
                if(dp[i][j]!=-1)
                {
                    flag=true;
                    for(k=0;k<n;k++){
                            if(ok[i][k]==0)
                                flag=false;
                            if(j!=k&&map[j][k]!=-1&&ok[i][k]!=2&&(dp[num[k]+i][k]==-1||dp[num[k]+i][k]>dp[i][j]+map[j][k]))
                               dp[num[k]+i][k]=dp[i][j]+map[j][k];
                    }
                    if(flag&&dp[i][j]<min)
                        min=dp[i][j];

                }
        if(min==INT_MAX)
            min=-1;
        printf("%d\n",min);

    }
    return 0;
}

 

posted on 2012-04-03 17:05  Goal  阅读(349)  评论(0编辑  收藏  举报

导航