标签:== ++ names string 一个 ret new org i+1
题面:https://www.luogu.org/problemnew/show/P1040
本题即一个在树上做的区间dp,只不过中间枚举的断点k即为当前dp到的树的根节点,然后将当前区间分为两段,即为树上的左子树和右子树,不过要注意这里的k可以取到端点值,即k的取值范围为[i,j]因为一棵树的左右子树可以为空,接着用dp方程f[i][j]=max(f[i][j],f[i][k-1]*f[k+1][j]+f[k][k])就能求解,那么前序遍历也就自然很好解决了。
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
const int N=35;
int n,front[N][N];
long long f[N][N];
void printf_front(int l,int r){
if(l>r){
return;
}
printf("%d ",front[l][r]);
if(l==r){
return;
}
printf_front(l, front[l][r]-1);
printf_front(front[l][r]+1,r);
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld", &f[i][i]);
f[i][i-1]=1;
f[i][i+1]=1;
front[i][i]=i;
}
for(int len=1;len<n;len++){
for(int i=1;i+len<=n;i++){
int j=i+len;
for(int 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];
front[i][j]=k;
}
}
}
}
printf("%lld\n",f[1][n]);
printf_front(1,n);
return 0;
}
标签:== ++ names string 一个 ret new org i+1
原文地址:https://www.cnblogs.com/ukcxrtjr/p/11194425.html