描述 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