TSP問題的狀態DP解法:
題意:從1點開始遍曆全圖的點後回到起點的最短路徑問題
因為TSP不限制每個點遍曆的次數,所以可以用floyd處理下兩點間的距離,之後DP處理下,
DP[i][j]表示狀態為二進位i下,當前遍曆第j個點的最小值,DP[1<<j][j]初始化為map[0][j]
#include <stdio.h>#include <string.h>#include <iostream>using namespace std;const int maxn=12;const int maxm=1<<11|1;int n;int map[maxn][maxn];int dp[maxm][maxn];void floyd(){ for (int k=0 ; k<=n ; ++k) for (int i=0 ; i<=n ; ++i) for (int j=0 ; j<=n ; ++j) if(map[i][j]>map[i][k]+map[k][j]) map[i][j]=map[i][k]+map[k][j];}int main (){ while (~scanf("%d",&n)&&n) { for (int i=0 ; i<=n ; ++i) for (int j=0 ; j<=n ; ++j) { scanf("%d",*(map+i)+j); } floyd(); memset (dp , 63 , sizeof(dp)); for (int i=0 ; i<(2<<n) ; ++i) { for (int j=0 ; j<=n ; ++j) { dp[1<<j][j]=map[0][j]; //if(i==1<<j)dp[i][j]=map[0][j];這個和上面的語句都能AC if(i&(1<<j)) for (int k=0 ; k<=n ; ++k) { if((i-(1<<j)) & (1<<k))//第k位為1,第j位不為1的狀態 dp[i][j]=min(dp[i-(1<<j)][k]+map[k][j],dp[i][j]); } //printf("%d %d %d\n",i,j,dp[i][j]); } } int ans=dp[(2<<n)-1][0]; for (int i=1 ; i<=n ; ++i) { ans=min(dp[(2<<n)-1][i]+map[i][0],ans); } printf("%d\n",ans); } return 0;}