Hie with the Pie(Floyd 状压DP)
POJ 3311 Hie with the Pie
題目大意
一個(gè)披薩店要請(qǐng)司機(jī)來(lái)送披薩,這家店最多接受10個(gè)訂單,由于預(yù)算的問(wèn)題,只能雇傭一名司機(jī),要求用最短的時(shí)間,從披薩店出發(fā)送完最后再回到披薩店(途中可能不止一次經(jīng)過(guò)一個(gè)地方)。
輸入
測(cè)試數(shù)據(jù)可能有多個(gè),第一行包含一個(gè)整數(shù) n n n ( 1 ≤ n ≤ 10 1 \leq n \leq 10 1≤n≤10),接下來(lái)的 n + 1 n+1 n+1行,每行包含 n + 1 n+1 n+1個(gè)整數(shù),披薩點(diǎn)的位置 0 0 0以及后面 n n n個(gè)位置,其中第 i i i行第 j j j個(gè)值表示從位置 i i i到達(dá)位置 j j j所用的時(shí)間(其中對(duì)于從 i i i到 j j j可能有更快捷的方式,數(shù)據(jù)不是對(duì)稱(chēng)的),當(dāng) n = 0 n=0 n=0時(shí),表示輸入結(jié)束
輸出
對(duì)于每一個(gè)測(cè)試用例輸出一個(gè)整數(shù),表示所花費(fèi)的最短的時(shí)間
樣例輸入
3 0 1 10 10 1 0 1 2 10 1 0 10 10 2 10 0 0樣例輸出
8分析
由于每?jī)蓚€(gè)地點(diǎn)的直接距離不一定是最短的,因此首先要用 f l o y d floyd floyd算法來(lái)更新所有點(diǎn)之間的最短距離
然后這個(gè)問(wèn)題就變成了典型的 T S P TSP TSP問(wèn)題,為了便捷的表示已經(jīng)被訪問(wèn)過(guò)的位置,可以使用二進(jìn)制來(lái)進(jìn)行壓縮,例如有 4 4 4個(gè)位置,分別是 0 , 1 , 2 , 3 0,1,2,3 0,1,2,3,其中 1 1 1和 2 2 2已經(jīng)被訪問(wèn)過(guò),那么二進(jìn)制表示為 ( 0110 ) 2 (0110)_2 (0110)2?,被訪問(wèn)過(guò)的頂點(diǎn)就用 1 1 1表示,沒(méi)訪問(wèn)過(guò)的用 0 0 0表示。這樣就可以將狀態(tài)壓縮到一個(gè)數(shù)組中去。就可以清楚的表示哪些頂點(diǎn)被訪問(wèn)過(guò),哪些沒(méi)有被訪問(wèn)。
其中 d [ s ] [ j ] d[s][j] d[s][j]表示,在當(dāng)前的 s s s的狀態(tài)下(已經(jīng)訪問(wèn)過(guò)的點(diǎn)),正處在 j j j的位置上回到頂點(diǎn)所花費(fèi)的最小時(shí)間。狀態(tài)轉(zhuǎn)移方程如下
d [ s ∣ 1 < < k ] [ k ] = m i n ( d [ s ∣ 1 < < k ] [ k ] ,    d [ s ] [ j ] + a [ j ] [ k ] ) d[s|1<<k][k] = min(d[s|1<<k][k],\,\,d[s][j]+a[j][k]) d[s∣1<<k][k]=min(d[s∣1<<k][k],d[s][j]+a[j][k])
其中點(diǎn) k k k表示下次要訪問(wèn)的點(diǎn),是從已經(jīng)訪問(wèn)過(guò)的點(diǎn) j j j轉(zhuǎn)移到下一個(gè)點(diǎn) k k k。更新完數(shù)組后
最終答案就是,枚舉所有的 d [ ( 1 < < n ) ? 1 ] [ i ] + a [ i ] [ 0 ]        ( 0 < i < n ) d[(1 << n) - 1][i] + a[i][0]\,\,\,\,\,\,(0<i<n) d[(1<<n)?1][i]+a[i][0](0<i<n),其中最小值就是答案。這句話的意思就是,訪問(wèn)所有頂點(diǎn)后,可能停留再任意一個(gè)地方 i i i,因此要枚舉每一個(gè)地方回到 0 0 0的時(shí)間。
代碼
#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出發(fā),二進(jìn)制中1表示第一個(gè)位置訪問(wèn)過(guò),所以置為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) //找到已經(jīng)訪問(wèn)過(guò)的點(diǎn)jfor(int k = 0; k < n; k++)if(!(s >> k & 1)) //找到?jīng)]有被訪問(wèn)過(guò)的點(diǎn)kd[s|1 << k][k] = min(d[s|1 << k][k], d[s][j] + a[j][k]); //從j點(diǎn)更新到k點(diǎn)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; }總結(jié)
以上是生活随笔為你收集整理的Hie with the Pie(Floyd 状压DP)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: syzkaller--->syscall
- 下一篇: ZigBee TI ZStack CC2