HDU 3001 Travelling:TSP(旅行商)【节点最多经过2次】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001

题意:

  有n个城市,m条双向道路,每条道路走一次需要花费路费v。你可以将任意一个城市作为起点出发,然后遍历每一个城市,并保证同一个城市最多经过2次。问你遍历这些城市的最小费用是多少。

 

题解:

  传统的TSP问题中,每个城市只能经过一次,做法为三重for循环,分别枚举城市的state、现在所处位置i、下一步要到达的城市j。

  

  核心Code:

 1 memset(dp,-1,sizeof(dp));
 2 dp[1<<start][start]=0;
 3 for(int state=0;state<(1<<n);state++)
 4 {
 5     for(int i=0;i<n;i++)
 6     {
 7         if(dp[state][i]!=-1)
 8         {
 9             for(int j=0;j<n;j++)
10             {
11                 if(i!=j && !((state>>j)&1))
12                 {
13                     if(dp[state|(1<<j)][j]==-1 || dp[state|(1<<j)][j]>dp[state][i]+dis[i][j])
14                     {
15                         dp[state|(1<<j)][j]=dp[state][i]+dis[i][j];
16                     }
17                 }
18             }
19         }
20     }
21 }

 

 

  在这道题中,与传统TSP的唯一区别是每个城市最多经过的次数由1次变为了2次。那么表示每座城市的状态state也应该相应改为用三进制数表示,每一位上的数字代表对应城市已经经过的次数。

  所以把所有的二进制改为三进制就好啦 ( ̄▽ ̄)~*

  注:不用对于每一个起点分别求一次dp,会T。。。在开始要把所有的dp[update(0, i)][i] = 0

 

AC Code:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <queue>
  5 #define MAX_N 15
  6 #define MAX_S 60000
  7 #define INF 100000000
  8 
  9 using namespace std;
 10 
 11 const int POW[]={1,3,9,27,81,243,729,2187,6561,19683,59049,177147,531441,1594323,4782969};
 12 
 13 int n,m;
 14 int a,b,v;
 15 int ans;
 16 int dis[MAX_N][MAX_N];
 17 int dp[MAX_S][MAX_N];
 18 
 19 void init()
 20 {
 21     for(int i=0;i<n;i++)
 22     {
 23         for(int j=0;j<n;j++)
 24         {
 25             dis[i][j]=INF;
 26             if(i==j) dis[i][j]=0;
 27         }
 28     }
 29 }
 30 
 31 void read()
 32 {
 33     for(int i=0;i<m;i++)
 34     {
 35         cin>>a>>b>>v;
 36         dis[a-1][b-1]=min(dis[a-1][b-1],v);
 37         dis[b-1][a-1]=min(dis[b-1][a-1],v);
 38     }
 39 }
 40 
 41 int query(int a,int k)
 42 {
 43     return a/POW[k]%3;
 44 }
 45 
 46 int update(int a,int k)
 47 {
 48     return a+POW[k];
 49 }
 50 
 51 bool check(int state)
 52 {
 53     for(int i=0;i<n;i++)
 54     {
 55         if(query(state,i)==0) return false;
 56     }
 57     return true;
 58 }
 59 
 60 void solve()
 61 {
 62     ans=INF;
 63     memset(dp,-1,sizeof(dp));
 64     for(int i=0;i<n;i++)
 65     {
 66         dp[update(0,i)][i]=0;
 67     }
 68     for(int state=0;state<POW[n];state++)
 69     {
 70         for(int i=0;i<n;i++)
 71         {
 72             if(dp[state][i]!=-1)
 73             {
 74                 for(int j=0;j<n;j++)
 75                 {
 76                     if(i!=j && query(state,j)<2)
 77                     {
 78                         int nex=update(state,j);
 79                         if(dp[nex][j]==-1 || dp[nex][j]>dp[state][i]+dis[i][j])
 80                         {
 81                             dp[nex][j]=dp[state][i]+dis[i][j];
 82                         }
 83                     }
 84                 }
 85                 if(check(state)) ans=min(ans,dp[state][i]);
 86             }
 87         }
 88     }
 89 }
 90 
 91 void print()
 92 {
 93     if(ans==INF) cout<<-1<<endl;
 94     else cout<<ans<<endl;
 95 }
 96 
 97 int main()
 98 {
 99     while(cin>>n>>m)
100     {
101         init();
102         read();
103         solve();
104         print();
105     }
106 }

 

posted @ 2017-08-15 19:07  Leohh  阅读(361)  评论(0编辑  收藏  举报