首页 > 其他 > 详细

[SPOJGCJ1C09C] Bribe the Prisoners

时间:2017-09-20 20:37:00      阅读:248      评论:0      收藏:0      [点我收藏+]

 

题意:有p个犯人,编号从1到p,现有q个犯人可以被释放,但是他两旁的所有犯人看到了觉得很不爽,所以要给1元钱来贿赂他们(请问他在监狱里到哪去花钱),一直到一个空监狱,要求安排q个犯人释放的顺序,使得总代价最小

 

题解:

区间dp

状态:dp[i][j]表示(i,j)的犯人被释放的最小代价

转移:dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+v[j]-v[i]-2)

初值:dp[i][i+1]=0

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #define ll long long
 8 using namespace std;
 9 
10 const int N = 110;
11 
12 int T,n,m,tot;
13 int v[N],dp[N][N];
14 
15 int gi() {
16   int x=0,o=1; char ch=getchar();
17   while(ch!=- && (ch<0 || ch>9)) ch=getchar();
18   if(ch==-) o=-1,ch=getchar();
19   while(ch>=0 && ch<=9) x=x*10+ch-0,ch=getchar();
20   return o*x;
21 }
22 
23 int main() {
24   T=gi();
25   while(T--) {
26     int p=gi(),q=gi();
27     for(int i=1; i<=q; i++) v[i]=gi();
28     v[q+1]=p+1;
29     memset(dp,63,sizeof(dp));
30     for(int i=0; i<=q; i++) dp[i][i+1]=0;
31     for(int l=1; l<=q; l++)
32       for(int i=0; i<=q+1; i++) {
33     int j=i+l+1;
34     for(int k=i+1; k<=j-1; k++) {
35       dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+v[j]-v[i]-2);
36     }
37       }
38     printf("Case #%d: %d\n", ++tot,dp[0][q+1]);
39   }
40   return 0;
41 }

总结:区间DP

这里的递推实际上是正常操作的一个逆过程

也就是相当于从子问题推出全局问题

所以要先推出范围较小一点的子区间

于是第一维枚举范围,第二维枚举起点,算出终点,第三维枚举中间点转移

[SPOJGCJ1C09C] Bribe the Prisoners

原文:http://www.cnblogs.com/HLXZZ/p/7563441.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!