日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hie with the Pie(Floyd 状压DP)

發布時間:2024/1/8 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hie with the Pie(Floyd 状压DP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

POJ 3311 Hie with the Pie

題目大意

一個披薩店要請司機來送披薩,這家店最多接受10個訂單,由于預算的問題,只能雇傭一名司機,要求用最短的時間,從披薩店出發送完最后再回到披薩店(途中可能不止一次經過一個地方)。

輸入

測試數據可能有多個,第一行包含一個整數 n n n ( 1 ≤ n ≤ 10 1 \leq n \leq 10 1n10),接下來的 n + 1 n+1 n+1行,每行包含 n + 1 n+1 n+1個整數,披薩點的位置 0 0 0以及后面 n n n個位置,其中第 i i i行第 j j j個值表示從位置 i i i到達位置 j j j所用的時間(其中對于從 i i i j j j可能有更快捷的方式,數據不是對稱的),當 n = 0 n=0 n=0時,表示輸入結束

輸出

對于每一個測試用例輸出一個整數,表示所花費的最短的時間

樣例輸入

3 0 1 10 10 1 0 1 2 10 1 0 10 10 2 10 0 0

樣例輸出

8

分析

由于每兩個地點的直接距離不一定是最短的,因此首先要用 f l o y d floyd floyd算法來更新所有點之間的最短距離

然后這個問題就變成了典型的 T S P TSP TSP問題,為了便捷的表示已經被訪問過的位置,可以使用二進制來進行壓縮,例如有 4 4 4個位置,分別是 0 , 1 , 2 , 3 0,1,2,3 0123,其中 1 1 1 2 2 2已經被訪問過,那么二進制表示為 ( 0110 ) 2 (0110)_2 (0110)2?,被訪問過的頂點就用 1 1 1表示,沒訪問過的用 0 0 0表示。這樣就可以將狀態壓縮到一個數組中去。就可以清楚的表示哪些頂點被訪問過,哪些沒有被訪問。

其中 d [ s ] [ j ] d[s][j] d[s][j]表示,在當前的 s s s的狀態下(已經訪問過的點),正處在 j j j的位置上回到頂點所花費的最小時間。狀態轉移方程如下

d [ s ∣ 1 &lt; &lt; k ] [ k ] = m i n ( d [ s ∣ 1 &lt; &lt; k ] [ k ] , &ThinSpace;&ThinSpace; d [ s ] [ j ] + a [ j ] [ k ] ) d[s|1&lt;&lt;k][k] = min(d[s|1&lt;&lt;k][k],\,\,d[s][j]+a[j][k]) d[s1<<k][k]=min(d[s1<<k][k],d[s][j]+a[j][k])

其中點 k k k表示下次要訪問的點,是從已經訪問過的點 j j j轉移到下一個點 k k k。更新完數組后

最終答案就是,枚舉所有的 d [ ( 1 &lt; &lt; n ) ? 1 ] [ i ] + a [ i ] [ 0 ] &ThinSpace;&ThinSpace;&ThinSpace;&ThinSpace;&ThinSpace;&ThinSpace; ( 0 &lt; i &lt; n ) d[(1 &lt;&lt; n) - 1][i] + a[i][0]\,\,\,\,\,\,(0&lt;i&lt;n) d[(1<<n)?1][i]+a[i][0](0<i<n),其中最小值就是答案。這句話的意思就是,訪問所有頂點后,可能停留再任意一個地方 i i i,因此要枚舉每一個地方回到 0 0 0的時間。

代碼

#include <cstdio> #include <cstring> #define N 11 #define INF 0x3f3f3f3f #define min(a,b) a>b?b:aint a[N][N]; int d[1 << N][N]; int n;inline void floyd() {for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)for(int k = 0; k < n; k++)a[i][j] = min(a[i][j], a[i][k] + a[k][j]); }int main () {while(1) {scanf("%d", &n);if(!n) break;n++;memset(d, INF, sizeof(d)); //初始化d[1][0] = 0; //從0出發,二進制中1表示第一個位置訪問過,所以置為0for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)scanf("%d", &a[i][j]);floyd();for(int s = 0; s < 1 << n; s++)for(int j = 0; j < n; j++)if(s >> j & 1) //找到已經訪問過的點jfor(int k = 0; k < n; k++)if(!(s >> k & 1)) //找到沒有被訪問過的點kd[s|1 << k][k] = min(d[s|1 << k][k], d[s][j] + a[j][k]); //從j點更新到k點int ans = INF;for(int i = 1; i < n; i++)ans = min(ans, d[(1 << n)-1][i] + a[i][0]);printf("%d\n", ans);}return 0; }

總結

以上是生活随笔為你收集整理的Hie with the Pie(Floyd 状压DP)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。