zoukankan      html  css  js  c++  java
  • cqyz oj/洛谷 | 释放囚犯 | 区间DP

    题目描述

    Caima王国中有一个奇怪的监狱,这个监狱一共有P个牢房,这些牢房一字排开,第i个紧挨着第i+1个(最后一个除外)。现在正好牢房是满的。

    上级下发了一个释放名单,要求每天释放名单上的一个人。这可把看守们吓得不轻,因为看守们知道,现在牢房中的P个人,可以相互之间传话。如果某个人离开了,那么原来和这个人能说上话的人,都会很气愤,导致他们那天会一直大吼大叫,搞得看守很头疼。如果给这些要发火的人吃上肉,他们就会安静点。

    输入格式

    第一行两个数P和Q,Q表示释放名单上的人数;

    第二行Q个数,表示要释放哪些人。

    数据规模

    对于100%的数据1≤P≤1000; 1≤Q≤100;Q≤P;且50%的数据 1≤P≤100;1≤Q≤5

    输出格式

    仅一行,表示最少要给多少人次送肉吃。

    输入 1

    20 3
    3 6 14

    输出 1

    35

    【样例说明】

    先释放14号监狱中的罪犯,要给1到13号监狱和15到20号监狱中的19人送肉吃;再释放6号监狱中的罪犯,要给1到5号监狱和7到13号监狱中的12人送肉吃;最后释放3号监狱中的罪犯,要给1到2号监狱和4到5号监狱中的4人送肉吃。


    设f[i][j]表示释放区间[i,j]的犯人需要的最小花费(其中i,j是要被释放的犯人,即下面的a[]的序号,不是监狱的序号)
    方程:

    [f[i][j]=min{f[i][k]+f[k+1][j]+a[j+1]-a[i-1]-1-1}a[j+1]-a[i-1]-1 ]

    就是这次释放的区间的人数,再-1是因为被放出去的那个囚犯不需要吃肉

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn = 105;
    
    int p, q;
    int f[maxn][maxn], a[maxn];
    int main(){
    	scanf("%d%d",&p,&q);
    	for(int i=1;i<=q;i++)scanf("%d",&a[i]);
    	sort(a+1,a+1+q);//有序才能转移
    	a[0] = 0;a[q+1] = p+1;//将0和q+1看成有人便于转移
    	
    	for(int len=1; len <= q; len++){//按区间长度dp
    		for(int i=1; i+len-1 <= q; i++){
    			int j = i+len-1;
    			f[i][j] = 0x3f3f3f3f;
    			for(int k=i;k<=j;k++)//省略了初始化f[i][i-1]为0
    				f[i][j] = min(f[i][j], f[i][k-1]+f[k+1][j]+a[j+1]-a[i-1]-1-1);
    		}
    	}
    	
    	printf("%d", f[1][q]);
    	return 0;
    }
    
  • 相关阅读:
    Redis--过期键策略(惰性删除、定期删除)
    Redis--数据库(个数16、键空间、过期字典、过期策略)
    Redis--事件(serverCron)
    ArrayList是如何扩容的?
    Java的四大引用类型
    类加载机制,双亲委派模型及其优点
    GC调优思路
    modcount的作用
    JVM的常见的垃圾收集器
    什么是临界区?如何解决冲突(也就是临界区的调度原则)?
  • 原文地址:https://www.cnblogs.com/de-compass/p/11390612.html
Copyright © 2011-2022 走看看