题解
第一次遇到区间dp的问题,这种解构问题的方法还是比较新颖的。
既然是dp,我们还是想要把全部的状态以及选择表达出来,怎样表示是个问题。
大概思路是
//mst(dp,0) 初始化DP数组
for(int i=1;i<=n;i++)
{
dp[i][i]=初始值
}
for(int len=2;len<=n;len++) //区间长度
for(int i=1;i<=n;i++) //枚举起点
{
int j=i+len-1; //区间终点
if(j>n) break; //越界结束
for(int k=i;k<j;k++) //枚举分割点,构造状态转移方程
{
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+w[i][j]);
}
}
ps: 这道题按这种思路是 O(n^3)的复杂度,还可以进一步优化。(平行四边形优化)
Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int n,m;
int cot[202],pre[202];
int f1[202][202],f2[202][202];
int d(int i,int j){
return pre[j] - pre[i-1];
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>cot[i];
cot[i+n] = cot[i];
}
for(int i=1;i<=n+n;i++) pre[i] = pre[i-1]+cot[i];
for(int len=1;len<n;len++){
for(int i=1,j=i+len;i<n+n && j< n+n;i++,j=i+len){// 环成链 i要迭代到n后面
f2[i][j] = 1e9;
for(int k=i;k<j;k++){
f1[i][j] = max(f1[i][j], f1[i][k]+f1[k+1][j]+d(i,j));
f2[i][j] = min(f2[i][j], f2[i][k]+f2[k+1][j]+d(i,j));
}
}
}
int maxp,minp;
maxp=0,minp=99999999;
for(int i=1;i<=n;i++){
maxp = max(maxp,f1[i][i+n-1]);
minp = min(minp,f2[i][i+n-1]);
}
cout<<minp<<endl<<maxp<<endl;
return 0;
}