//Floyd + 狀態壓縮DP<br />//題意是有N個城市(1~N)和一個PIZZA店(0),要求一條迴路,從0出發,又回到0,而且距離最短<br />//也就是TSP(旅行商)問題,首先不難想到用FLOYD先求出任意2點的距離dis[i][j]<br />//接著枚舉所有狀態,用11位二進位表示10個城市和pizza店,1表示經過,0表示沒有經過<br />//定義狀態DP(S,i)表示在S狀態下,到達城市I的最優值<br />//接著狀態轉移方程:DP(S,i) = min{DP(S^(1<<i-1),k) + dis[k][j],DP(S,i)},器重S^(1<<i-1)表示未到達城市i的所有狀態,1<=k<=n<br />//對於全1的狀態,即S = (1<<n)-1則表示經過所有城市的狀態,最終還需要回到PIZZA店0<br />//那麼最終答案就是min{DP(S,i) + dis[i][0]}<br />#include<iostream><br />#define INF 100000000<br />using namespace std;<br />int dis[12][12];<br />int dp[1<<11][12];<br />int n,ans,_min;<br />int main()<br />{<br />//freopen("in.txt","r",stdin);<br />while(scanf("%d",&n) && n)<br />{<br />for(int i = 0;i <= n;++i)<br />for(int j = 0;j <= n;++j)<br />scanf("%d",&dis[i][j]);<br />for(int k = 0;k <= n;++k)<br />for(int i = 0;i <= n;++i)<br />for(int j = 0;j <= n;++j)<br />if(dis[i][k] + dis[k][j] < dis[i][j])<br />dis[i][j] = dis[i][k] + dis[k][j];</p><p>for(int S = 0;S <= (1<<n)-1;++S)//枚舉所有狀態,用位元運算表示<br />for(int i = 1;i <= n;++i)<br />{<br />if(S & (1<<(i-1)))//狀態S中已經過城市i<br />{<br />if(S == (1<<(i-1)))dp[S][i] = dis[0][i];//狀態S只經過城市I,最優解自然是從0出發到i的dis,這也是DP的邊界<br />else//如果S有經過多個城市<br />{<br />dp[S][i] = INF;<br />for(int j = 1;j <= n;++j)<br />{<br />if(S & (1<<(j-1)) && j != i)//枚舉不是城市I的其他城市<br />dp[S][i] = min(dp[S^(1<<(i-1))][j] + dis[j][i],dp[S][i]);<br />//在沒經過城市I的狀態中,尋找合適的中間點J使得距離更短,和FLOYD一樣<br />}<br />}<br />}<br />}<br />ans = dp[(1<<n)-1][1] + dis[1][0];<br />for(int i = 2;i <= n;++i)<br />if(dp[(1<<n)-1][i] + dis[i][0] < ans)<br />ans = dp[(1<<n)-1][i] + dis[i][0];<br />printf("%d/n",ans);<br />}<br />return 0;<br />}