zoukankan      html  css  js  c++  java
  • $Luogu$ $P1040$ 加分二叉树

    链接

    背景

    (CCF) (NOIP2003) (T3)(Luogu) (P1040)

    题意

    设一棵二叉树(形态未知)的中序遍历是 ({ 1,2,3,cdots,n }) 。给定这 (n) 个节点的权值,规定一棵子树的得分是左右子树得分之积加上根节点权值的结果。请构造出一棵满足题意的树使得得分最大,并求出最大得分和树的先序遍历。注意叶节点的得分是本身权值,仅有一棵子树的节点另一棵空子树得分记为 (1)

    解法

    不是树形 (dp) 模板。是习题。
    然而我死活想不出解。后来发现我把中序遍历和先序遍历搞混淆了。
    由于构造出来的树要满足中序遍历的要求,则选定 (x) 点为子树 ([l,r]) 的根之后左子树只能为 ([l,x-1]) ,右子树只能为 ([x+1,r]) 。于是就有了最优子结构性质。
    (f_{l,r}) 表示中序遍历是 ({ l,l+1,l+2,cdots,r }) 的子树的最大得分。则转移应当枚举其中的一个点作为这棵子树的根,再递归计算左右子树的值。
    于是考虑记忆化搜索(本质是动态规划的递归实现形式),状态转移是 (f_{l,r}=max_limits{k in [l,r]} { f_{l,k-1} imes f_{k+1,r}+val_k }) 。要求的就是 (f_{l,r})
    最后考虑怎么输出先序遍历。由于先根、后左子、最后右子,于是在 (dp) 的时候可以给每棵子树 ([l,r]) 确定一个根节点 (root_{l,r}) ,做完之后从 ([1,n]) 开始递归输出即可,先输出根节点,再递归左子树,最后递归右子树。

    细节

    (1.) 两个边界:子树为空(即 (l>r) )时显然得分只能为 (0) ;子树仅有一个节点(即 (l=r) ,是一个叶节点)时显然得分就是本身权值。

    (2.) 注意输出时为了避免递归不停止,在子树为空(即 (l>r) )时直接 (return)

    $View$ $Code$ ```cpp #include using namespace std; inline int read() { int ret=0,f=1; char ch=getchar(); while('9'ans) { ans=nowans; anspos=i; } } rt[l][r]=anspos; return f[l][r]=ans; } void print(int l,int r) { if(r
  • 相关阅读:
    2.Android之按钮Button和编辑框EditText学习
    《DSP using MATLAB》Problem 3.8
    《DSP using MATLAB》Problem 3.7
    《DSP using MATLAB》Problem 3.6
    《DSP using MATLAB》Problem 3.5
    《DSP using MATLAB》Problem 3.4
    《DSP using MATLAB》Problem 3.3
    《DSP using MATLAB》Problem 3.2
    《DSP using MATLAB》Problem 3.1
    《DSP using MATLAB》Problem 2.20
  • 原文地址:https://www.cnblogs.com/Peter0701/p/11838643.html
Copyright © 2011-2022 走看看