【题目描述】
Caima 王国中有一个奇怪的监狱,这个监狱一共有 P 个牢房,这些牢房一字排开,
第 i 个仅挨着第 i+1 个(最后一个除外)。现在正好牢房是满的。
上级下发了一个释放名单,要求每天释放名单上的一个人。这可把看守们吓得不
轻,因为看守们知道,现在牢房中的 P 个人,可以互相之间传话。如果某个人离开了,
那么原来和这个人能说上话的人,都会很气愤,导致他们那天会一直大吼大叫,搞得
看守很头疼。如果给这些要发火的人吃上肉,他们就会安静点。
现在看守们想知道,如何安排释放的顺序,才能使得他们花费的肉钱最少。
【输入格式】
第一行两个数 P 和 Q,Q 表示释放名单上的人数;
第二行 Q 个数,表示要释放哪些人。
【输出格式】
仅一行,表示最少要给多少人次送肉吃。
【数据规模】
1<=P<=1000;1<=Q<=100。
【输入样例】
20 3
3 6 14
【输出样例】
35
【注意事项】
Q<=P;且 50%的数据 1<=P<=100;1<=Q<=5。
区间dp
令f[i][j]表示释放了i~j的最小费用
f[i][j]=min(f[i][k-1]+f[k+1][j]+(a[j+1]-a[i-1]))
其实是一个逆推的过程
我们从结果f[i][i]一步步推到f[1][q]
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int a[1002],p,q,f[1002][1002]; 8 int main() 9 {int i,j,k,s=0; 10 cin>>p>>q; 11 for (i=1;i<=q;i++) 12 { 13 scanf("%d",&a[i]); 14 } 15 a[q+1]=p+1;a[0]=0; 16 memset(f,127/3,sizeof(f)); 17 for (i=1;i<=q;i++) 18 f[i][i]=a[i+1]-a[i-1]-2; 19 for (i=2;i<=q;i++) 20 { 21 for (j=1;j+i-1<=q;j++) 22 { 23 for (k=j;k<=j+i-1;k++) 24 { 25 s=0; 26 if (k>=j+1) 27 s+=f[j][k-1]; 28 if (k<j+i-1) 29 s+=f[k+1][j+i-1]; 30 s+=a[j+i]-a[j-1]-2; 31 f[j][j+i-1]=min(f[j][j+i-1],s); 32 } 33 } 34 } 35 cout<<f[1][q]; 36 }