1. 程式人生 > 實用技巧 >石子合併(區間狀態模板)

石子合併(區間狀態模板)

石子合併

在一個圓形操場的四周擺放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;
}