白书上的一题(区间dp) 2009 Round 1C C
题意:
给定一条长为p并排的牢房,给定q个需要释放的罪犯,罪犯编号为顺序,当释放其中一个罪犯的时候吗,要给此罪犯两旁的罪犯每人一枚金币(直到遇见空牢房或者到牢房两端为止) 求这样释放罪犯使花费的金币最少
思路:如果把所有的释放方式都排列一遍求最小值 复杂度为q!,,超时
理解题意可知,如果每释放一个罪犯,就相当于把牢房分成了两部分,,然后依次下去,,就构成了dp思想的树模型,,解决每个子问题到解决父问题
好了,照着白书写的代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<algorithm> #include<map> #define maxn 200005 #define inf 10000000; using namespace std; int p,q,a[maxn]; int dp[10005][10005]; int main() { cin>>p>>q; for(int i=1;i<=q;i++) cin>>a[i]; for(int i=0;i<=q;i++) dp[i][i+1]=0; a[0]=0; a[q+1]=p+1; for(int i=2;i<=q+1;i++) for(int j=0;j+i<=q+1;j++) { int zz=j+i; int t=inf; for(int k=j+1;k<zz;k++) t=min(t,dp[j][k]+dp[k][zz]); dp[j][zz]=t+a[zz]-a[j]-2; } cout<<dp[0][q+1]<<endl; return 0; }