ssl1597-石子合并问题【区间dp练习】
在一個圓形操場的四周擺放著n 堆石子。現要將石子有次序地合并成一堆。規定每次只能選相鄰的2 堆石子合并成新的一堆,并將新的一堆石子數記為該次合并的得分。試設計一個算法,計算出將n堆石子合并成一堆的最小得分和最大得分。
編程任務:
對于給定n堆石子,編程計算合并成一堆的最小得分和最大得分。
Input
輸入包括多組測試數據,每組測試數據包括兩行。
第1 行是正整數n,1<=n<=100,表示有n堆石子。
第2行有n個數,分別表示每堆石子的個數。
Output
對于每組輸入數據,輸出兩行。
第1 行中的數是最小得分;第2 行中的數是最大得分。
Sample Input
4
4 4 5 9
Sample Output
43
54
解題思路
? 看這題之前請補一下:http://blog.csdn.net/mr_wuyongcong/article/details/78815773
? 這道題是石子合并的升級版,這里把改成了圓形,那么說明第一堆和最后一堆也可以合并,這道題我用了一種不同的方法。可以先把所有兩個的和在一起,再把所有的三個的合在一起......以此類推。然后列出動態轉移方程:
? mins=min(mins,f[i][k]+f[k+1][j]+s[j]-s[i-1])
? maxs=max(maxs,f1[i][k]+f1[k+1][j]+s[j]-s[i-1])
還是代碼講的清楚
代碼
#include<cstdio>
#include<iostream>
using namespace std;
int n,x,s[201],f[201][201],f1[201][201],maxs,mins,a[201];
int main()
{
? scanf("%d",&n);
? for (int i=1;i<=n;i++)
? {
? ? scanf("%d",&a[i]);
? ? a[n+i]=a[i];//環狀相連
? }
? for (int i=1;i<=2*n;i++)
? s[i]=s[i-1]+a[i];//預處理不解釋
? for (int ii=2;ii<=n;ii++)//如我所說↑
? ? for (int i=1;i<=2*n-ii+1;i++)//枚舉開頭
? ? {
int mins=2147483647,maxs=0,j=i+ii-1;//如我所說↑
for (int k=i;k<j;k++)//枚舉分裂點
{
?mins=min(mins,f[i][k]+f[k+1][j]+s[j]-s[i-1]);
? maxs=max(maxs,f1[i][k]+f1[k+1][j]+s[j]-s[i-1]);
? //動態轉移方程
}
f[i][j]=mins;//最小值存入
f1[i][j]=maxs;//最大值存入
? ? }
? int mins=2147483647,maxs=0;
? for (int i=1;i<=n;i++)
? {
? ? maxs=max(maxs,f1[i][i+n-1]); //求每個區域的最大值
? ? mins=min(mins,f[i][i+n-1]); //求每個區域的最小值
? }
? printf("%d\n%d",mins,maxs);//get√
}
總結
以上是生活随笔為你收集整理的ssl1597-石子合并问题【区间dp练习】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么的小草 什么的小草填空
- 下一篇: ssl1056-金明的预算方案【dp之有