HDU---Travelling(三進位制狀態壓縮)
阿新 • • 發佈:2018-12-14
題意:題意:Mr ACMer想要進行一次旅行,他決定訪問n座城市。Mr ACMer 可以從任意城市出發,必須訪問所有的城市至少一次,並且任何一個城市訪問的次數不能超過2次。n座城市間有m條道路,每條道路都有一個費用。求Mr ACMer 完成旅行需要花費的最小費用。如果不能完成旅行,則輸出-1。
思路:每個點最多隻能被訪問2次,用3進位制來壓縮狀態,0,1,2分別表示走該點0,1,2次.要注意列舉點的時候,路徑和點的對應關係.
假設有3個城市 1 1 0表示前2個城市被訪問了1次,第3個城市還沒被訪問,化成十進位制就是12(這裡是3進位制化化十進位制)
詳細可見程式碼
#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; int dp[60000][12]; int cost[12][12]; int three[12]; int digit[60000][12];///digit[i][j]表示狀態為i,第j為是多少(0,1,2),也就是在狀態i下,從第1個城/ 市到第10個城市分別被訪問了幾次,這裡n最多隻能取到10; void init() { three[0]=1; for(int i=1;i<=10;i++) three[i]=three[i-1]*3; for(int i=0;i<three[10];i++) { int temp=i; for(int j=0;j<10;j++) { digit[i][j]=temp%3; temp/=3; } } } int main() { ios::sync_with_stdio(false); init(); int n,m; while(cin>>n>>m) { memset(cost,inf,sizeof(cost)); for(int i=0;i<three[n];i++) for(int j=0;j<n;j++) dp[i][j]=inf; while(m--) { int u,v,w; cin>>u>>v>>w; cost[u-1][v-1]=cost[v-1][u-1]=min(cost[u-1][v-1],w); } for(int i=0;i<n;i++) dp[three[i]][i]=0; ///dp[i][j]的意思為 在狀態i下,最後走到的城市為第j個城市. int ans=inf; for(int i=0;i<three[n];i++)///列舉狀態 { bool flag=1; for(int j=0;j<n;j++)///列舉最後到達的城市 { if(digit[i][j]==0) flag=0;///如果最後到達的城市是走過的話那麼就可以更新一次答案 if(dp[i][j]!=inf)///保證是從起點出發 for(int k=0;k<n;k++) if(cost[j][k]!=inf&&digit[i][k]!=2)///j到k之間是有路的,而且k城市沒有被訪問2次 { dp[i+three[k]][k]=min(dp[i+three[k]][k],dp[i][j]+cost[j][k]); ///最後訪問的城市就變成了k } } if(flag) { for(int j=0;j<n;j++) ans=min(ans,dp[i][j]); } } if(ans>=inf) cout<<-1<<endl; else cout<<ans<<endl; } return 0; }