Hie with the Pie(Floyd+状压dp)
描述
傳送門:poj-3311
?The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately, due to cutbacks, they can afford to hire only one driver to do the deliveries. He will wait for 1 or more (up to 10) orders to be processed before he starts any deliveries. Needless to say, he would like to take the shortest route in delivering these goodies and returning to the pizzeria, even if it means passing the same location(s) or the pizzeria more than once on the way. He has commissioned you to write a program to help him.
Input
Input will consist of multiple test cases. The first line will contain a single integer n indicating the number of orders to deliver, where 1 ≤ n ≤ 10. After this will be n + 1 lines each containing n + 1 integers indicating the times to travel between the pizzeria (numbered 0) and the n locations (numbers 1 to n). The jth value on the ith line indicates the time to go directly from location i to location j without visiting any other locations along the way. Note that there may be quicker ways to go from i to j via other locations, due to different speed limits, traffic lights, etc. Also, the time values may not be symmetric, i.e., the time to go directly from location i to j may not be the same as the time to go directly from location j to i. An input value of n = 0 will terminate input.
Output
For each test case, you should output a single number indicating the minimum time to deliver all of the pizzas and return to the pizzeria.
Examples
intput
1
2
3
4
5
63
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0output
1 8
題目大意
給你一個有$n+1$,$(1<=n<=10)$個點的有向完全圖,用矩陣的形式給出任意兩個不同點之間的距離。(其中從$i$到$j$的距離不一定等于從$j$到$i$的距離)現在要你求出從$0$號點出發,走過$1$到$n$號點至少一次,然后再回到$0$號點所花的最小時間。
思路
- 先用floyd $O(n^3)$預處理出任意兩個點之間的最短距離。
- 用一個11位的二進制數表示狀態,1表示要經過這個點,0表示不經過。
- $dp[state][j]$: 在$state$狀態下$0$點到達$j$點的最短路。如果state狀態里面經過了i,并且沒有經過j,那么就能通過dp[state][i]更新dp[state|(1<<j)][j]。
- 這道題的狀態和狀態轉移方程和zoj-3471很像:
代碼
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | /* Problem: 3311 User: Armin Memory: 396K Time: 0MS Language: G++ Result: Accepted */ using namespace std; const int N=11; int Map[N][N],dp[1<<N][N],n; int main() { while(scanf("%d",&n),n++){ rep(i,0,n) rep(j,0,n) scanf("%d",&Map[i][j]); rep(k,0,n) //floy預處理出任意兩個點之間的最短距離 rep(i,0,n) rep(j,0,n) if(Map[i][j]>Map[i][k]+Map[k][j]) Map[i][j]=Map[i][k]+Map[k][j]; rep(i,0,1<<n) //初始化成無窮大 rep(j,0,n) dp[i][j]=Max; dp[0][0]=0; //0點在0狀態到0點的距離為0 rep(state,0,1<<n) rep(i,0,n){ if(dp[state][i]==Max) continue; //剪枝:只有當dp[state][i]不等于Max時才可能更新 if(i&&state==(1<<i)) //如果state狀態只經過了i一個點,注意這里要把i==0的情況去點,因為i==0在33行已經處理了,這里1<<0 ==1 !=0 所以這里里更新會出錯。 dp[state][i]=Map[0][i]; else rep(j,0,n) if(((1<<j)&state)==0) //如果沒經過j城市 dp[state|(1<<j)][j]=min(dp[state|(1<<j)][j],dp[state][i]+Map[i][j]); } int ans=Max; rep(i,1,n) ans=min(ans,dp[(1<<n)-1][i]+Map[i][0]); //找最優解+回來的路 printf("%d\n",ans); } return 0; } |
總結
以上是生活随笔為你收集整理的Hie with the Pie(Floyd+状压dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue-router路由防卫
- 下一篇: 《围城》摘抄