poj 3311 Hie with the Pie
题意:
一个人要送pizza到一些地方,一个地方可以进过两次,这样经过中转的时间可能会更短。
问送完pizza会到原点的最少时间。
思路:
状压dp + Floyd?
经典的tsp问题,不过并没有想到用Floyd求最短距离。
我的做法是,更新一个状态时,更新两次,第一次更新最新的点,第二次更新经过中转点的最短距离,跟Floyd还是有相同之处的。
转移方程:
dp[S|(1<<k)][k] = min(dp[S|(1<<k)][k],dp[S][j]),j属于S集合。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 const int N = 12; 6 const int inf = 0x3f3f3f3f; 7 int dp[(1<<N)][N]; 8 int mp[N][N]; 9 int main() 10 { 11 int n; 12 while (scanf("%d",&n)!=EOF&&n) 13 { 14 n++; 15 for (int i = 0;i < n;i++) 16 { 17 for (int j = 0;j < n;j++) scanf("%d",&mp[i][j]); 18 } 19 memset(dp,inf,sizeof(dp)); 20 dp[1][0] = 0; 21 for (int i = 0;i < (1<<n);i++) 22 { 23 for (int j = 0;j < n;j++) 24 { 25 if (!i&(1<<j)) continue; 26 if (dp[i][j] >= inf) continue; 27 for (int k = 0;k < n;k++) 28 { 29 dp[i|(1<<k)][k] = min(dp[i|(1<<k)][k],dp[i][j]+mp[j][k]); 30 } 31 } 32 for (int j = 0;j < n;j++) 33 { 34 if (!i&(1<<j)) continue; 35 if (dp[i][j] >= inf) continue; 36 for (int k = 0;k < n;k++) 37 { 38 dp[i|(1<<k)][k] = min(dp[i|(1<<k)][k],dp[i][j]+mp[j][k]); 39 } 40 } 41 } 42 printf("%d\n",dp[(1<<n)-1][0]); 43 } 44 return 0; 45 }
康复训练中~欢迎交流!