http://acm.nankai.edu.cn/p1137.html
只有相邻的石子才能合并成堆,十分类似矩阵连乘问题,这里是形成了环,另d[i][j] 表示从第i个元素开始,共j个石子堆的最小得分,c[i][j]表示最大考虑n<=100,n^2的复杂度可行,各种在处理环时不细心啊
// category: dp
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn=105;
int n ;
int d[maxn][maxn],c[maxn][maxn];
int sum[maxn];
int a[maxn];
void solve()
{
for (int l=2;l<=n;++l)
{
for (int i=0;i<n;++i)
{
d[i][l]=99999999;
c[i][l]=0;
for (int j=1;j<l;++j)
{
int s1,s2;
int k=(i+j-1)%n;
if (k<i) s1=sum[n-1]-sum[i-1]+sum[k] ;
else if(i==0) s1=sum[k];
else s1=sum[k]-sum[i-1];
int r=(i+l-1)%n;
if (r<k) s2=sum[n-1]-sum[k]+sum[r];
else s2=sum[r]-sum[k];
int ans1=d[i][j]+d[(i+j)%n][l-j]+s2+s1;
int ans=c[i][j]+c[(i+j)%n][l-j]+s2+s1;
d[i][l]=d[i][l]>ans1 ? ans1:d[i][l];
c[i][l]=c[i][l]>ans ? c[i][l]:ans;
}
}
}
int min=d[0][n],max=d[0][n];
for (int i=1;i<n;++i)
{
if (min>d[i][n])
min=d[i][n];
if (max<c[i][n])
max=c[i][n];
}
printf("%d\n%d\n",min,max);
}
int main(){
while(~scanf("%d",&n)){
memset(sum,0,sizeof(sum));
scanf("%d",&a[0]);
sum[0]=a[0];
for (int i=1;i<n;++i){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
solve();
}
return 0;
}