加分二叉树 NOIP2003 提高组区间dp
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加分二叉树 NOIP2003 提高组区间dp相关的知识,希望对你有一定的参考价值。
原题链接
状态表示:
f
[
l
]
[
r
]
f[l][r]
f[l][r]表示的是选取区间
[
l
,
r
]
[l,r]
[l,r]作为一棵树的最大值
转移方程:
f
[
l
]
[
r
]
=
m
a
x
(
f
[
l
]
[
r
]
,
l
e
f
t
∗
r
i
g
h
t
+
a
[
k
]
)
f[l][r] = max(f[l][r], left * right + a[k])
f[l][r]=max(f[l][r],left∗right+a[k])
k
枚举的是根节点
#include<bits/stdc++.h>
using namespace std;
const int N = 35;
int a[N];
int f[N][N],g[N][N];
int n;
void dfs(int l,int r)
{
if(l>r) return ;
int root = g[l][r];
cout<<root<<' ';
dfs(l,root-1);
dfs(root+1,r);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int len = 1;len<=n;len++)
{
for(int l = 1;l+len-1<=n;l++)
{
int r = l+len-1;
if(len==1)//长度只为1时,该点就为根节点
{
f[l][r] = a[l];
g[l][r] = l;
}
else
{
for(int k=l;k<=r;k++)//枚举根节点
{
int left = k==l ? 1 : f[l][k-1];//看根节点是否是左端点,若是,左子树为空
int right = k==r ? 1 : f[k+1][r];//看根节点是否是右端点,若是,右子树为空
int s = left * right + a[k];
if(s > f[l][r])
{
f[l][r] = s;
g[l][r] = k;
}
}
}
}
}
cout<<f[1][n]<<'\\n';
dfs(1,n);
return 0;
}
以上是关于加分二叉树 NOIP2003 提高组区间dp的主要内容,如果未能解决你的问题,请参考以下文章
cogs 106. [NOIP2003] 加分二叉树(区间DP)