P1622

释放囚犯

题目描述

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

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

输入格式

第一行两个整数 \(P\)\(Q\)\(Q\) 表示释放名单上的人数;

第二行 \(Q\) 个整数,表示要释放哪些人,保证按递增的顺序给出。

输出格式

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

样例 #1

样例输入 #1

20 3
3 6 14

样例输出 #1

35

提示

样例说明 #1

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

数据规模与约定

-对于 \(50\%\) 的数据,\(1 \le P \le 100\)\(1 \le Q \le 5\)
-对于 \(100\%\) 的数据,\(1 \le P \le 10^3\)\(1 \le Q \le 100\)\(Q \le P\),保证释放的人所在的牢房编号按递增的顺序给出。

区间DP
但还是有点疑惑 先挂着
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int p,q,a[105],f[1005][1005];
signed main()
{
	ios::sync_with_stdio(false);
	cin>>p>>q;
	for(int i=1;i<=q;i++)cin>>a[i];
	a[0]=0,a[q+1]=p+1;
//	memset(f,0x3f,sizeof(f));
//	for(int i=1;i<=q;i++)f[i][i]=a[i+1]-a[i-1]-2;
	for(int l=1;l<=q;l++)
		for(int i=1;i<=q;i++)
		{
			int j=i+l-1;
			f[i][j]=LONG_MAX;
			for(int k=i;k<=j;k++)
				f[i][j]=min(f[i][j],f[i][k-1]+f[k+1][j]+a[j+1]-a[i-1]-2);
		}
	cout<<f[1][q]<<"\n";
	return 0;
}

感觉还是这种思路好理解一点:

点击查看代码
#include<cstdio>
#include<iostream>
#include<cstring>
#define rep(i,a,b) for (int i=(a); i<=(b); i++)
#define clr(x) memset(x,-1,sizeof(x));
using namespace std;
int n,m,f[105][105],a[105];
int ans(int l, int r) {
    if (f[l][r]!=-1) return f[l][r];
    f[l][r]=0x7f7f7f7f;
    rep(i,l+1,r-1) f[l][r]=min(f[l][r],ans(l,i)+ans(i,r)+a[r]-a[l]-2);
    return f[l][r];
}
int main()
{
    scanf("%d%d",&n,&m); clr(f);
    rep(i,1,m) scanf("%d",&a[i]); a[0]=0; a[m+1]=n+1;
    rep(i,0,m) f[i][i+1]=0;
    printf("%d",ans(0,m+1));
    return 0;
}
posted @ 2023-01-10 20:43  PKU_IMCOMING  阅读(5)  评论(0)    收藏  举报