tzhsoj1590 prison

题目描述

Caima王国中有一个奇怪的监狱,这个监狱一共有P个牢房,这些牢房一字排开,第i个紧挨着第i+1个(最后一个除外)。现在正好牢房时满的。 上 级下发了一个释放名单,要求每天释放名单上的一个人。这可把看守们吓得不轻,因为看守们知道,现在牢房中的P个人,可以相互之间传话。如果某个人离开了,那么原来和这个人能说上话的人,都会很气愤,导致他们那天会一直大吼大叫,搞得看守很头疼。如果给这些要发火的人吃上肉,他们就会安静点。

输入

第一行两个数P和Q,Q表示释放名单上的人数; 第二行Q个数,表示要释放哪些人。 【数据规模】 1≤P≤1000; 1≤Q≤100 【注意事项】 Q≤P;且50%的数据 1≤P≤100;1≤Q≤5

输出

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

样例输入

20 3
3 6 14

样例输出

35

提示

【注意事项】
Q≤P;且50%的数据 1≤P≤100;1≤Q≤5

来源

 容易发现,如果某个犯人被释放了,就相当于出现了两个互不相干的监狱,那么就区间dp一下咯。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <cmath>
 
using namespace std;
 
const int N = 1010;
 
int n, q, man[N], f[N][N], out[N];
 
int solve(int l, int r) {
    if(l > r) return 0;
 
    if(f[l][r] != -1) return f[l][r];
 
    f[l][r] = 0x3f3f3f3f;
 
    for(int i = l ; i <= r ; i ++)
        if(out[i] == 1)
            f[l][r] = min(f[l][r], r - l + solve(l, i - 1) + solve(i + 1, r));
 
    if(f[l][r] == 0x3f3f3f3f) f[l][r] = 0;
 
    return f[l][r];
}
 
int main() {
    // freopen("oi.in", "r", stdin);
    memset(f, -1, sizeof(f));
    scanf("%d%d", &n, &q);
    for(int i = 1 ; i <= q; i ++) scanf("%d", &man[i]), out[man[i]] = 1;
    printf("%d\n", solve(1, n));
}

  

posted @ 2017-09-06 17:41  KingSann  阅读(281)  评论(0编辑  收藏  举报