spoj14846 Bribe the Prisoners
Posted yzxverygood
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spoj14846 Bribe the Prisoners相关的知识,希望对你有一定的参考价值。
看来我还是太菜了,这么一道破题做了那么长时间......
分析
我首先想到的是用状压dp来转移每一个人是否放走的状态,但是发现复杂度远远不够。于是我们考虑区间dp,dpij表示i到j区间的所有罪犯全部放走的最小花费,于是我们可以将一个区间(i,j)分为(i,k-1),(k+1,j)和k这个点,表示先取走点k的人,这样这个区间就被分成了两个,于是我们便可以转移的。详见代码。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int pl[1100],dp[1100][1100];
inline void init(){
memset(dp,0x7f,sizeof(dp));
}
int main(){
int n,m,i,j,k,t;
scanf("%d",&t);
for(int _=1;_<=t;_++){
init();
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++)
scanf("%d",&pl[i]);
pl[n+1]=m+1;
for(i=1;i<=n;i++)
dp[i][i]=pl[i+1]-pl[i-1]-2;
for(i=2;i<=n;i++)
for(j=1;j+i-1<=n;j++){
dp[j][j+i-1]=min(dp[j+1][j+i-1],dp[j][j+i-2]);
for(k=j+1;k<j+i-1;k++)
dp[j][j+i-1]=min(dp[j][j+i-1],dp[j][k-1]+dp[k+1][j+i-1]);
dp[j][j+i-1]+=pl[j+i]-pl[j-1]-2;
}
printf("Case #%d: ",_);
printf("%d
",dp[1][n]);
}
return 0;
}
以上是关于spoj14846 Bribe the Prisoners的主要内容,如果未能解决你的问题,请参考以下文章
[SPOJGCJ1C09C] Bribe the Prisoners
SPOJ CIRU The area of the union of circles