#include<bits/stdc++.h>
using namespace std;
const int MAXN=33;
int root[MAXN][MAXN]={};
int dp[MAXN][MAXN]={};
vector<int> ppp;
void print(int l,int r){
if(l>r) return;
if(l==r){
cout<<l<<' ';return;
}
printf("%d ",root[l][r]);
print(l,root[l][r]-1);
print(root[l][r]+1,r);
}
int main()
{
freopen("in.txt","r",stdin);
int n;cin>>n;
//fill(dp[0],dp[0]+MAXN*MAXN,1);
for(int i=1;i<=n;i++){
int w;cin>>w;
dp[i][i]=w;
dp[i][i-1]=1;//空树分值为1
}
for(int i=n;i>=1;i--){//i是逆序枚举,用到dp[k+1][j]时已经提前计算出来了
for(int j=i+1;j<=n;j++){
for(int k=i;k<=j;k++){
if(dp[i][j]<(dp[i][k-1]*dp[k+1][j]+dp[k][k])){
dp[i][j]=dp[i][k-1]*dp[k+1][j]+dp[k][k];root[i][j]=k;
}
}
}
}
cout<<dp[1][n]<<endl;
print(1,n);
return 0;
}
事实证明这道题逆序正序都可以做
#include<bits/stdc++.h>
using namespace std;
const int MAXN=33;
int root[MAXN][MAXN]={};
int dp[MAXN][MAXN]={};
vector<int> ppp;
void print(int l,int r){
if(l>r) return;
if(l==r){
cout<<l<<' ';return;
}
printf("%d ",root[l][r]);
print(l,root[l][r]-1);
print(root[l][r]+1,r);
}
int main()
{
freopen("in.txt","r",stdin);
int n;cin>>n;
//fill(dp[0],dp[0]+MAXN*MAXN,1);
for(int i=1;i<=n;i++){
int w;cin>>w;
dp[i][i]=w;
dp[i][i-1]=1;//空树分值为1
}
for(int len=2;len<=n;len++){//以区间长度为元素进行正序dp
for(int i=1;i<=n;i++){
int j=i+len-1;
for(int k=i;k<=j;k++){
if(dp[i][j]<(dp[i][k-1]*dp[k+1][j]+dp[k][k])){
dp[i][j]=dp[i][k-1]*dp[k+1][j]+dp[k][k];root[i][j]=k;
}
}
}
}
cout<<dp[1][n]<<endl;
print(1,n);
return 0;
}
本文介绍了一种使用区间动态规划求解最优二叉树的算法,通过逆序或正序枚举区间长度,计算出使二叉树得分最大的划分方式。算法首先初始化每个节点的得分,并递归地计算所有可能的子树得分,最终输出最优二叉树的得分及结构。
638

被折叠的 条评论
为什么被折叠?



