石子合併(區間狀態模板)
阿新 • • 發佈:2020-08-21
石子合併
在一個圓形操場的四周擺放N堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。
試設計出一個演算法,計算出將N堆石子合併成1堆的最小得分和最大得分。
輸入格式
資料的第1行是正整數N,表示有N堆石子。
第2行有N個整數,第ii個整數ai表示第i堆石子的個數。
輸出格式
輸出共2行,第1行為最小得分,第2行為最大得分。
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int n,i,j,k,L;
int Min=0x7fffffff/2;
int Max=0;
int a[205],sum[205];
int f1[205][205],f2[205][205];
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
a[i+n]=a[i];
}
for(i=1;i<=2*n;i++)
sum[i]=sum[i-1]+a[i];
for(i=1;i<=2*n;i++)
{
f1[i][i]=0;
f2[i][i]=0;
}
for(L=2;L<=n;L++)
for(i=1;i<=2*n-L+1;i++)
{
j=i+L-1;
f1[i][j]=0x7fffffff/2;
f2[i][j]=0;
for(k=i;k<j;k++)
{
f1[i][j]=min(f1[i][j],f1[i][k]+f1[k+1][j]);
f2[i][j]=max(f2[i][j],f2[i][k]+f2[k+1][j]);
}
f1[i][j]+=sum[j]-sum[i-1];
f2[i][j]+=sum[j]-sum[i-1];
}
for(i=1;i<=n;i++)
{
Min=min(f1[i][i+n-1],Min);
Max=max(f2[i][i+n-1],Max);
}
cout<<Min<<endl<<Max;
}