hdu3001 Travelling 三进制状态压缩

来源:互联网 发布:版权局 网络音乐 编辑:程序博客网 时间:2024/05/22 12:00

题意: Mr.Acmer 希望能走遍所有的城市,但他不会进入一个城市超过两次。 每次从一个城市到另一个城市需要一定的消耗,求他总共最少的消耗量。如果他不能在条件允许下走遍所有城市则输出-1。

由数据量可知,城市数量仅为个位数的数量级,非常少。所以可以用状态压缩来做,对每一个城市而言,有三种状态。我们用0表示为走过,1表示走过1次,2表示走过两次。

map[ i ][ j ] 来存储 i 号城市到 j 号城市所需要的消耗。 dp[ i ][ j ] :i 状态下,以 j 号城市为最后落脚点所需的最少消耗量。

dp[ i ][ j ] = min ( dp[ p ][ k ] +map[ k ][ j ] )  

预处理出状态 i 下三进制每一位数,存在s[ i ] 中。

#include<iostream>#include<cstdio>#include<string.h>#include<algorithm>using namespace std;#define INF 0x1f1f1f1fint three[11],s[59060][11],dp[59060][11];int n,m,map[11][11];void pretreat()//预处理每个状态i : 十进制数换三进制数后每一位数什么{    int i,p,up;    three[0]=1;    for(i=1;i<11;i++)    {        three[i]=three[i-1]*3;    }    for(i=0;i<three[10];i++)    {        p=i;        up=0;        while(p!=0)        {            s[i][up++]=p%3;            p/=3;        }    }}int main(){    int i,j,k,r;    pretreat();    while(scanf("%d%d",&n,&m)!=EOF)//忘记写!=EOF  我te了16次,还在那不断得各种优化。。我艹。。    {        memset(dp,INF,sizeof(dp));        int x,y;        for(i=0;i<n;i++)            for(j=0;j<n;j++)            map[i][j]=INF;        for(i=0;i<m;i++)        {            scanf("%d%d",&x,&y);            scanf("%d",&map[x-1][y-1]);            map[y-1][x-1]=map[x-1][y-1]=min(map[x-1][y-1],map[y-1][x-1]);        }        for(i=0;i<n;i++)//初始化超人把他送到任意位置开始时的值        {            dp[three[i]][i]=0;        }        dp[0][0]=0;        int ans=INF;        for(i=1;i<three[n];i++)//枚举状态        {            int flag=0;            for(j=0;j<n;j++)//枚举每一个给状态下最后一个到达的点            {                if(s[i][j]==0) flag=1;                if(dp[i][j]==INF)  continue;                for(k=0;k<n;k++)//枚举下一个将要到达的点                {                    if(j==k||s[i][k]==2||map[j][k]==INF)  continue;                    int ret=i+three[k];                    dp[ret][k]=min(dp[ret][k],dp[i][j]+map[j][k]);                }            }            if(flag==0)            {                for(r=0;r<n;r++)                {                    ans=min(ans,dp[i][r]);                }            }        }        if(ans==INF) printf("-1\n");        else printf("%d\n",ans);    }    return 0;}


原创粉丝点击