https://www.luogu.org/problemnew/show/P1040
将f[i][j]
视为 i 到 j 上的最大值, 计算规则依题意. 对于空结点表示1, 用f[i][j] , i>j
来处理. 依据循环的边界条件, 只需要对f[i][i-1]
以及f[N+1][N]
做处理即可.
循环过程类似石子合并.
#include <bits/stdc++.h>
#define FF(a,b) for(int a=0;a<b;a++)
#define F(a,b) for(int a=1;a<=b;a++)
#define LEN 40
#define bug(x) cout<<#x<<"="<<x<<endl;
using namespace std;
int N;
int f[LEN][LEN];
int root[LEN][LEN];
int cnt=0;//空格计数
inline void print_num(int num){
printf("%d",num);
cnt++;
if(cnt<N) putchar(' ');
}
void print(int l,int r){
if(l>r) return;
int m=root[l][r];
print_num(m);
if(l==r) return;
print(l,m-1);
print(m+1,r);
}
int main()
{
freopen("./in","r",stdin);
cin>>N;
F(i,N){
cin>>f[i][i];
f[i][i-1]=1; //空结点为0
root[i][i]=i;
}
f[N+1][N]=1;
for(int d=1;d<N;d++){//间隔
for(int i=1;i+d<=N;i++){//开始
int j=i+d;//结束
root[i][j]=i;
f[i][j]=f[i][i]+f[i+1][j];
for(int k=i+1;k<=j;k++){ //分割
int tmp_fij=f[k][k]+f[i][k-1]*f[k+1][j];
if(tmp_fij>f[i][j]){
f[i][j]=tmp_fij;
root[i][j]=k;
}
}
}
}
cout<<f[1][N]<<endl;
print(1,N);
return 0;
}