題目描述
在一個圓形操場的四周擺放N堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記爲該次合併的得分。
試設計出1個算法,計算出將N堆石子合併成1堆的最小得分和最大得分.
輸入格式
數據的第1行試正整數N,1≤N≤100,表示有N堆石子.第2行有N個數,分別表示每堆石子的個數.
輸出格式
輸出共2行,第1行爲最小得分,第2行爲最大得分.
輸入輸出樣例
輸入 #1複製
4 4 5 9 4
輸出 #1複製
43 54
#include <bits/stdc++.h>
using namespace std;
int s[1000],f1[300][300],f2[300][300],n=0,num[1000];
int d(int i,int j){
return s[j]-s[i-1];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n+n;i++){
if(i<=n)scanf("%d",&num[i]);
num[i+n]=num[i];
s[i]=s[i-1]+num[i];
}
for(int p=1;p<n;p++)
for(int i=1,j=i+p;(i<n*2)&&(j<n*2);i++,j=i+p){
f2[i][j]=65536;
for(int k=i;k<j;k++){
f1[i][j]=max(f1[i][j],f1[i][k]+f1[k+1][j]+d(i,j));
f2[i][j]=min(f2[i][j],f2[i][k]+f2[k+1][j]+d(i,j));
}
}
int minv=65536,maxv=0;
for(int i=1;i<=n;i++){
maxv=max(maxv,f1[i][i+n-1]);
minv=min(minv,f2[i][i+n-1]);
}
cout<<minv<<endl<<maxv;
return 0;
}