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;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号