Code[VS] 1090 加分二叉树
来源:互联网 发布:我的淘宝如何换帐号 编辑:程序博客网 时间:2024/06/09 04:52
【题意】
已知:一颗树tree,n,d[N]
条件:①有结点1..n,每个点有分数d[i],tree满足中序遍历为1..n
②子树subtree的加分计算方法为:左子树加分×右子树加分+根的分数
③空子树加分为1,叶子的加分就是叶节点本身的分数,不考虑它的空子树。
求:一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree,输出 ①tree的最高加分 ②tree的前序遍历
【构思】
树有无后效性-->树形DP;
由于满足中序遍历,所以一颗子树的结点编号必然在一连续区间内;
设f[l][r]表示区间[l,r]的最大加分,rt[l][r]为最大加分时rt是什么;
边界:f[l][r]=1(l>r),f[l][r]=d[l](l=r)
方程:f[l][r]=max(f[l][i-1]+f[i+1][r]+d[i])
结果即f[1][n],且得到rt后直接可以建树,2问都解决了;
时间复杂度:O(n^3)
空间复杂度:O(n^2)
【实现】
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MIN -5000000000
using namespace std;
const int N=31;
int n,d[N],rt[N][N],s[N];
long long f[N][N];
void init(void)
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&d[i]);
}
long long DFS(int l,int r)
{
if (l>r) return 1;
if (f[l][r]^MIN) return f[l][r];
for (int i=l;i<=r;i++)
{
long long t=DFS(l,i-1)*DFS(i+1,r)+d[i];
if (f[l][r]<t)
{
f[l][r]=t;
rt[l][r]=i;
}
}
return f[l][r];
}
void Get(int l,int r)
{
if (l>r) return;
if (l==r) {s[++s[0]]=l;return;}
s[++s[0]]=rt[l][r];
Get(l,rt[l][r]-1);
Get(rt[l][r]+1,r);
}
void work(void)
{
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j++) f[i][j]=(i==j?d[i]:MIN);
printf("%lld\n",DFS(1,n));
Get(1,n);
for (int i=1;i<n;i++) printf("%d ",s[i]);
printf("%d\n",s[n]);
}
int main(void)
{
init();
work();
return 0;
}
【回顾】
[1] DP无后效性的判定 ①空间的单项变化 ②数值的单调变化 ③树结构
[2] 树的遍历的性质
①单独性质
前序遍历 第1个为根 一段区间在后[i,i+size[i]-1]
中序遍历 当序列满足1..n时,子树也为连续区间 排序
后序遍历 最后为根 一段区间在前[i-size[i]+1,i]
②关联性质
遍历长度相同
[3] 树的遍历:搜索
[4] 数据类型大的变量可以加小的变量,小的不能加大的
- Code[VS] 1090 加分二叉树
- code vs 1090 加分二叉树 (树形DP)
- Cpp环境【NOIP2003 P3】【Vijos1100】【Code[VS]1090】【CQYZOS2816】加分二叉树
- 1090 加分二叉树
- CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树 /CodeVS 1090 加分二叉树
- 加分二叉树
- 1078 加分二叉树
- 加分二叉树_DP
- 加分二叉树
- 二叉树--面试加分
- 加分二叉树
- vijos1100 加分二叉树
- 加分二叉树
- Codevs1090 加分二叉树
- 加分二叉树
- NOIP2003 加分二叉树
- P1073 加分二叉树
- ssl1033 加分二叉树
- NOIP 2014 普及组 T4 子矩阵
- Code[VS] 1021 玛丽卡 题解
- Code[VS] 1022 覆盖
- 图论——最短路径
- sicily_1012 (计算几何)
- Code[VS] 1090 加分二叉树
- C语言指针系列四——指针与函数
- LeetCodeOJ. Linked List Cycle
- ENVI自学笔记一
- Android开发者必须知道的内存管理知识
- Code[VS] 3301 Square words
- Code[VS] 1436 孪生素数2
- Code[VS] 2046 孪生素数3
- 【Codechef】February Challenge 2015 Chef and Strings