第一个答案总是会大一点
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,a[40010],f1[5010][5010],f2[5010][5010],s[40010];
//f1[l][r]表示从l到r合并的最小代价
//f2[l][r]表示从l到r合并的最大代价
//s为前缀和
//先用k切成2部分,[l][k]和[k+1][r]
//f1[l][k]+f1[k+1][r]+s[r]-s[l-1]->取最小值f1[l][r]
//f2[l][k]+f2[k+1][r]+s[r]-s[l-1]->取最大值f2[l][r]
int main(){
ios::sync_with_stdio(false),cin.tie(),cout.tie();
cin>>n;
memset(f1,0x3f3f,sizeof(f1));
memset(f2,0,sizeof(f2));
for(int i=1;i<=n;i++){
cin>>a[i];
f1[i][i]=0;
f2[i][i]=0;
s[i]=s[i-1]+a[i];
}
for(int len=2;len<=n;len++){
for(int l=1;l+len-1<=n;l++){
int r=l+len-1;
for(int k=l;k<r;k++){
f1[l][r]=min(f1[l][r],f1[l][k]+f1[k+1][r]+s[r]-s[l-1]);
}
}
}
for(int len=2;len<=n;len++){
for(int l=1;l+len-1<=n;l++){
int r=l+len-1;
for(int k=l;k<r;k++){
f2[l][r]=max(f2[l][r],f2[l][k]+f2[k+1][r]+s[r]-s[l-1]);
}
}
}
cout<<f1[1][n]<<endl<<f2[1][n];
return 0;
}
/*
in
4
4 5 9 4
out
43
54
*/