p1292监狱(动态规划)

描述 Description
小X的王国中有一个奇怪的监狱,这个监狱一共有P个牢房,这些牢房一字排开,第i个仅挨着第i+1个(最后一个除外),当然第i个也挨着第i-1个(第一个除外),现在牢房正好是满员的。
上级下发了一个释放名单,要求每天释放名单上的一个人。这可把看守们吓得不轻,因为看守们知道,现在牢房里的P个人,可以相互之间传话。第i个人可以把话传给第i+1个,当然也能传给第i-1个,并且犯人很乐意把消息传递下去。
如果某个人离开了,那么原来和这个人能说上话的人,都会很气愤,导致他们那天会一直大吼大叫,搞得看守很头疼。如果给这些要发火的人吃上肉,他们就会安静下来。
为了河蟹社会,现在看守们想知道,如何安排释放的顺序,才能是的他们消耗的肉钱最少。


输入格式 Input Format
第一行两个数P和Q,Q表示释放名单上的人数;
第二行Q个数,表示要释放哪些人。


输出格式 Output Format
仅一行,表示最少要给多少人次送肉吃。


样例输入 Sample Input
20 3
3 6 14


样例输出 Sample Output
35
样例解释: 先放14号犯人,给19个人肉吃,再放6号犯人,给12个人肉吃,最后放3号,给4个人肉吃,一共35个。


时间限制 Time Limitation
1s


注释 Hint
【数据规模】
1<=P<=1000; 1<=Q<=100.
Q<=P,且 50%的数据 1<=P<=100;1<=Q<=5;


来源 Source
codejam 

        (还是得回来搞动规哇)

        这道题就是一个区间动态规划的题,因为一共要放出来m个罪犯,但是没放出来一个罪犯后,能和这个罪犯说到话的人都会很生气,所以必须要给他们吃肉。。。。。所以就用一个数组sun[i]来记录释放第i个罪犯前需要支付的肉之和,然后用f[i][j]表示释放i到j中的罪犯最少需要多少肉,所以就可以知接在i到j中枚举出k,所以

        f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]+j-i-1);

//动规还是掌握的不好啊还得多写点题

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int a[1100];
int f[1100][1100];
int sum[1110];
int main()
{
    memset(a,0,sizeof(a));
    memset(f,10,sizeof(f));
    memset(sum,0,sizeof(sum));
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
        cin>>a[i];
    sort(a+1,a+1+m);
    for(int i=1;i<=m;i++)
    {
        sum[i]=a[i]-a[i-1]-1;
        f[i][i]=0;
    }
    sum[m+1]=n-a[m];
    for(int i=1;i<=m+1;i++)
        sum[i]=sum[i]+sum[i-1];
    f[0][0]=0;
    f[m+1][m+1]=0;
    for(int i=m+1;i>=1;i--)
    {
        for(int j=i+1;j<=m+1;j++)
        {
            for(int k=i;k<j;k++)
            {
                f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]+j-i-1);
            }
        }
    }
    cout<<f[1][m+1]<<endl;
    return 0;
}
ε(┬┬﹏┬┬)3

 

posted @ 2017-09-14 11:14  列車員lcy  阅读(362)  评论(0编辑  收藏  举报