以前觉得难
想想以前还是naive
然而我还是用的记搜
令人害怕的题也没那么难,qwq
(root(i,j))表示区间([i,j])的根。
CODE:
#include<iostream>
#include<cstdio>
using namespace std;
int n, a[31];
int f[31][31], root[31][31];
int dfs(int l, int r){
if(f[l][r]>0)return f[l][r];
if(r<l)return 1;
for(int i=l; i<=r; i++){
int p=dfs(l, i-1)*dfs(i+1, r)+f[i][i];
if(p>f[l][r]) f[l][r]=p, root[l][r]=i;
}
return f[l][r];
}
void print(int l, int r){
if(r<l)return;
if(l==r){
printf("%d ", l);return;
}
printf("%d ", root[l][r]);
print(l, root[l][r]-1);
print(root[l][r]+1, r);
}
int main(){
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d", &f[i][i]);
printf("%d
", dfs(1, n));
print(1, n);
return 0;
}
区间DP做法:
#include<iostream>
#include<cstdio>
using namespace std;
int n,v[39],f[47][47],i,j,k,root[49][49];
void print(int l,int r){
if(l>r)return;
if(l==r){printf("%d ",l);return;}
printf("%d ",root[l][r]);
print(l,root[l][r]-1);
print(root[l][r]+1,r);
}
int main() {
scanf("%d",&n);
for( i=1; i<=n; i++) scanf("%d",&v[i]);
for(i=1; i<=n; i++) {f[i][i]=v[i];f[i][i-1]=1;}
for(i=n; i>=1; i--)
for(j=i+1; j<=n; j++)
for(k=i; k<=j; k++) {
if(f[i][j]<(f[i][k-1]*f[k+1][j]+f[k][k])) {
f[i][j]=f[i][k-1]*f[k+1][j]+f[k][k];
root[i][j]=k;
}
}
printf("%d
",f[1][n]);
print(1,n);
return 0;
}