1. 程式人生 > >HDU 3001 Travelling:TSP(旅行商)

HDU 3001 Travelling:TSP(旅行商)

sta init using 多少 b- upd eof == als

題目鏈接: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 }

HDU 3001 Travelling:TSP(旅行商)