HDU3001-Travelling-状态压缩

来源:互联网 发布:舆论是什么知乎 编辑:程序博客网 时间:2024/05/22 13:43

题目大意:给你一张图,有n个节点,有m条边,每条边都有它的权值,你的任务是访问每个顶点不超过两次,但每个点一定要被访问过一次,问你最少花费多少;

题目解析:首先看到n这么小,肯定是状态压缩了,dp[i][j]表示以第i个点为结束点,j为状态序列的时候所表示的最少花费,注意这里的状态表示要用3进制,这样就能表示两次了,状态转移的时候只要枚举即可,初始条件只要初始每个点作为起始点即可;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#define inf 0x3fffffffusing namespace std;int mo[15][59051],dp[15][59051];int main(){    int n,m,ma[16][16],thd[16],a,b,c,i,j,k,temp,flag,ans,s;    memset(mo,0,sizeof(mo));    for(i=0;i<=59050;i++)    {        temp=i;        for(j=1;j<=10;j++)        {            mo[j][i]=temp%3;            temp=temp/3;            if(temp==0)                break;            }        }    thd[1]=1;    for(i=2;i<=15;i++)    {        thd[i]=thd[i-1]*3;    }    while(scanf("%d%d",&n,&m)!=EOF)    {        ans=inf;        for(i=0;i<=11;i++)        {            for(j=0;j<=59050;j++)            {                dp[i][j]=inf;            }        }         for(i=0;i<=12;i++)        {            for(j=0;j<=12;j++)                ma[i][j]=inf;        }        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&a,&b,&c);            if(c<ma[a][b])                ma[a][b]=ma[b][a]=c;        }        for(i=1;i<=n;i++)             dp[i][thd[i]]=0;           for(j=0;j<thd[n+1];j++)        {            flag=1;            for(i=1;i<=n;i++)            {                if(mo[i][j]==0)                {                    flag=0;                    continue;                }                for(k=1;k<=n;k++)                {                    if(k==i)    continue;                    if(ma[i][k]==inf||mo[k][j]>=2)    continue;                    s=j+thd[k];                    dp[k][s]=min(dp[k][s],dp[i][j]+ma[i][k]);                }            }            if(flag==1)            {                for(i=1;i<=n;i++)                {                    ans=min(ans,dp[i][j]);                }                }        }                if(ans==inf)            printf("-1\n");        else             printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击