hdu3001Travelling【三进制TSP】

Problem Description
After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice!He has decided to visit n cities(he insists on seeing all the cities!And he does not mind which city being his start station because superman can bring him to any city at first but only once.), and of course there are m roads here,following a fee as usual.But Mr Acmer gets bored so easily that he doesn't want to visit a city more than twice!And he is so mean that he wants to minimize the total fee!He is lazy you see.So he turns to you for help.
 

Input
There are several test cases,the first line is two intergers n(1<=n<=10) and m,which means he needs to visit n cities and there are m roads he can choose,then m lines follow,each line will include three intergers a,b and c(1<=a,b<=n),means there is a road between a and b and the cost is of course c.Input to the End Of File.
 

Output
Output the minimum fee that he should pay,or -1 if he can't find such a route.
 

Sample Input
   
   
   
   
2 1 1 2 100 3 2 1 2 40 2 3 50 3 3 1 2 3 1 3 4 2 3 10
 

Sample Output
   
   
   
   
100 90 7
 

Source
2009 Multi-University Training Contest 11 - Host by HRBEU
 

又是不好好读题惹的祸==“he doesn't want to visit a city more than twice”!!!最多两次!!

开始以为是裸的二进制旅行商问题,还纳闷为啥第二题过的那么多,这个题没几个人做呢==然后又十分笨拙的写了一个四进制,本想省事0-未走;1-走过一次;2-走过两次;3-无意义。发现代码调试不成功orz 又努力的写三进制,所以说,预处理出两个数组是十分有必要的,科科~~

vis[][]表示当前状态某点走过几次

/*************
hdu3001
2016.3.25
265MS	6704K	1638 B	G++
*************/
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define inf 0x3f3f3f3f
int min(int a,int b){if(a<b)return a;return b;}
int num[11][11],dp[60000][11];//twice!!
int vis[60000][11],state[12];
int n,m,ans;
void init()
{
    state[0]=1;
    for(int i=1;i<11;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++)
        {
            vis[i][j]=tmp%3;
            tmp/=3;
        }
    }
}
int main()
{
   // freopen("cin.txt","r",stdin);
    init();
    while(~scanf("%d%d",&n,&m))
    {
        memset(num,inf,sizeof(num));
        memset(dp,inf,sizeof(dp));
        while(m--)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(num[--a][--b]>c) num[a][b]=num[b][a]=c;
        }
        ans=inf;
        for(int i=0;i<n;i++)dp[state[i]][i]=0;
        for(int i=0;i<state[n];i++)
        {
            bool f=true;
            for(int j=0;j<n;j++)
            {
                if(vis[i][j]==0)f=false;
                if(dp[i][j]==inf)continue;
                for(int k=0;k<n;k++)
                    if(j!=k)
                    {
                        if(vis[i][k]>=2)continue;
                        if(num[j][k]==inf)continue;
                        dp[i+state[k]][k]=min(dp[i+state[k]][k],dp[i][j]+num[j][k]);
                    }
            }
            if(f)
            for(int j=0;j<n;j++)
            ans=min(ans,dp[i][j]);
        }
        if(ans<inf) printf("%d\n",ans);
        else printf("-1\n");
    }
    return 0;
}


你可能感兴趣的:(杭电,状态压缩dp)