白书上的一题(区间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;
}

 

posted @ 2018-03-19 20:39  姿态H  阅读(218)  评论(0编辑  收藏  举报