分析:与石子合并只加了一个环形的条件
对于环形问题,如果只是枚举中断点的话,在石子合并的基础上多开一维,时间复杂度是O(n^4)
可以采用一个普遍的方法,就是把环转换成一个链
通过把从1展开的链接在n的后面,这样子枚举的时候枚举以 位置2 断开的链,只需要枚举 以2开始,长度为len的链,就可以枚举n与1相邻的情况了
状态转移方程基本和石子合并一样,不同点在于环的存在,导致循环枚举不同
for(int len=1;len<=n;len++)
for(int l=1;l+len-1<=2*n;l++)
{//由于模拟中间断点,把前面断开的接到数组后面去,所以最大可能枚举到2n
...
}
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=410;
int a[N];
int s[N];
int dp[N][N];
int g[N][N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],a[n+i]=a[i];
for(int i=1;i<=2*n;i++) s[i]=s[i-1]+a[i];
memset(dp,0x3f,sizeof dp),memset(g,-0x3f,sizeof g);
for(int len=1;len<=n;len++)
for(int l=1;l+len-1<=2*n;l++)
{
int r=l+len-1;
if(len==1) dp[l][r]=g[l][r]=0;
else
for(int k=l;k<r;k++)
{
dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+s[r]-s[l-1]);
g[l][r]=max(g[l][r],g[l][k]+g[k+1][r]+s[r]-s[l-1]);
}
}
int maxv=-0x3f3f3f3f,minv=0x3f3f3f3f;
for(int i=1;i<=n;i++)
minv=min(minv,dp[i][i+n-1]),maxv=max(maxv,g[i][i+n-1]);
cout<<minv<<endl<<maxv<<endl;
return 0;
}