TSP問題 動態規劃實現
阿新 • • 發佈:2019-01-01
貨郎擔問題(TSP)。有n個城市,兩兩之間均有路直接連線,求一條經過每個城市一次且僅一次,最後返回起點的最短路線。
這是劉汝佳書上的一道題,他給出了思路,我實現了一下。
用動態規劃解決,可以假設從0點出發,然後回到0點。那麼用 f(i,S)表示現在處在i點,要去訪問剩餘的在集合S中的點,集合S可以用二進位制數st。
那麼狀態轉移方程就是:f(i,S)=min{d(j,S-{j})+dist(i,j)|j屬於S}
程式碼:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; int dis[12][12],f[1<<12][12],pos[1<<12][12]; //f[st][i]表示處在i點,還要訪問集合st的點各一次後返回0點的最短路 int main() { int n; // freopen("f.txt","r",stdin); while(~scanf("%d",&n)){ for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ scanf("%d",&dis[i][j]); //dis[i][j]=s[i][j]; } } int b=1<<(n-1); memset(f,-1,sizeof(f)); for(int i=0;i<n;i++) //邊界處理 f[0][i]=dis[i][0]; //st是空集,表示都已經訪問完了,剩餘路程就是從i點回到0點 for(int st=1;st<b-1;st++){ for(int i=1;i<n;i++){ if(st&(1<<(i-1)))continue; //如果i點在集合中沒訪問,那麼f[st][i]這個狀態就不成立 int minn=INF; for(int j=1;j<n;j++){ //列舉從i點要去j點 if(st&(1<<(j-1))){ //保證j點在集合st中 int tmp=dis[i][j]+f[st^(1<<(j-1))][j]; //把j點從st集合中去掉 if(tmp<minn){ //更新最小值 minn=tmp; f[st][i]=tmp; pos[st][i]=j; //記錄路徑 } } } } } int minn=INF; for(int k=1;k<n;k++){ int tmp=f[(b-1)^(1<<(k-1))][k]+dis[0][k]; if(tmp<minn) minn=tmp,f[b-1][0]=tmp,pos[b-1][0]=k;; } printf("%d\n",f[b-1][0]); // printf("0\n"); //列印路徑 // for(int st=b-1,next=0;st;){ // next=pos[st][next]; // printf("%d\n",next); // st=st^(1<<(next-1)); // } // printf("0\n"); } return 0; }