[SPOJGCJ1C09C] Bribe the Prisoners

Posted HLX_Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SPOJGCJ1C09C] Bribe the Prisoners相关的知识,希望对你有一定的参考价值。

 

题意:有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的主要内容,如果未能解决你的问题,请参考以下文章

Bribe the Prisoners

spoj14846 Bribe the Prisoners

C09 指针

codeforces #407(div1c div 2e)The Great Mixing

CodeForces - 1486C2 Guessing the Greatest (hard version)(二分+交互)

[LeetCode] 1417. Reformat The String