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