hdu 3001 三进制状压

题意:tsp问题,但是每个点可以最多走两次

链接:点我

转移方程见代码

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

#define inf 0x3f3f3f3f

int State[12];

int vis[60000][12];

int dp[60000][12];

int map[12][12];

int n,m;



void Initiate()

{

    State[0]=1;

    for(int i=1;i<=10;i++)

        State[i]=State[i-1]*3;      //初始城市

    for(int i=0;i<=State[10];i++)

    {

        int tmp=i;

        for(int j=0;j<=10;j++)  //点j在状态里出现的次数

        {

            vis[i][j]=tmp%3;

            tmp/=3;

        }

    }

}



int main()

{

    Initiate();

    int u,v,w,ans;

    #ifndef ONLINE_JUDGE

    freopen("1.in","r",stdin);

    #endif

    while(~scanf("%d%d",&n,&m)){

        memset(dp,inf,sizeof(dp));

        memset(map,inf,sizeof(map));

        for(int i=0;i<n;i++)dp[State[i]][i]=0;

        while(m--){

            scanf("%d%d%d",&u,&v,&w);

            u--,v--;

            map[u][v]=map[v][u]=min(map[u][v],w);

        }

        ans=inf;

        for(int i=0;i<State[n];i++) //枚举起点

        {

            bool flag=true;

            for(int j=0;j<n;j++)    //枚举终点

            {

                if(vis[i][j]==0)    flag=false;//是否每个城市都至少走了1次

                if(dp[i][j]==inf)   continue;

                for(int k=0;k<n;k++)    //枚举另一点

                    if(j!=k)

                    {

                        if(vis[i][k]>=2)continue;

                        if(map[j][k]==inf)continue;

                        dp[i+State[k]][k]=min(dp[i+State[k]][k],dp[i][j]+map[j][k]);

                    }

            }

            if(flag)

            {

                for(int j=0;j<n;j++)

                {

                    ans=min(ans,dp[i][j]);

                }

            }

        }

        if(ans==inf)    ans=-1;

        printf("%d\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(HDU)