zoukankan      html  css  js  c++  java
  • 加分二叉树 树形DP

    题意/Description

        设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点编号。每个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下: 
      subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数 
      若某个子树为主,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空子树。 
        试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree。要求输出; 
          (1)tree的最高加分 
          (2)tree的前序遍历 

     

    读入/Input

        第1行:一个整数n(n<30),为节点个数。 

        第2行:n个用空格隔开的整数,为每个节点的分数(分数<100)。 

     

    输出/Output

        第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。 
        第2行:n个用空格隔开的整数,为该树的前序遍历。 

     

    题解/solution

       很显然,本题适合用动态规划来解。如果用数组value[i,j]表示从节点i到节点j所组成的二叉树的最大加分,则动态方程可以表示如下:

           F[l,r]=max{f[l,r],f[l,i-1]*f[i+1,r]+a[i]}

        题目还要求输出最大加分树的前序遍历序列,因此必须在计算过程中记下从节点i到节点j所组成的最大加分二叉树的根节点,用数组g[i,j]表示。记录很简单,大家都会的啦。


    代码/Code

    var
      g:array [0..51,0..51] of longint;
      f:array [0..51,0..51] of int64;
      a:array [0..51] of longint;
      n:longint;
    procedure doit(l,r:longint);
    var
      i:longint;
    begin
      if f[l,r]>0 then exit;
      if l=r then
        begin
          f[l,r]:=a[l];
          g[l,r]:=l;
          exit;
        end;
      if l>r then
        begin
          f[l,r]:=1;
          exit;
        end;
      for i:=l to r do
        begin
          doit(l,i-1);
          doit(i+1,r);
          if f[l,i-1]*f[i+1,r]+a[i]>f[l,r] then
            begin
              f[l,r]:=f[l,i-1]*f[i+1,r]+a[i];
              g[l,r]:=i;
            end;
        end;
    end;
    
    procedure show(l,r:longint);
    begin
      if l<=r then
        begin
          write(g[l,r],' ');
          show(l,g[l,r]-1);
          show(g[l,r]+1,r);
        end;
    end;
    
    procedure init;
    var
      i:longint;
    begin
      readln(n);
      for i:=1 to n do
        read(a[i]);
      fillchar(f,sizeof(f),0);
      fillchar(g,sizeof(g),0);
    end;
    
    begin
      init;
      doit(1,n);
      writeln(f[1,n]);
      show(1,n);
    end.
    
  • 相关阅读:
    Leetcode Reverse Words in a String
    topcoder SRM 619 DIV2 GoodCompanyDivTwo
    topcoder SRM 618 DIV2 MovingRooksDiv2
    topcoder SRM 618 DIV2 WritingWords
    topcoder SRM 618 DIV2 LongWordsDiv2
    Zepto Code Rush 2014 A. Feed with Candy
    Zepto Code Rush 2014 B
    Codeforces Round #245 (Div. 2) B
    Codeforces Round #245 (Div. 2) A
    Codeforces Round #247 (Div. 2) B
  • 原文地址:https://www.cnblogs.com/zyx-crying/p/9319715.html
Copyright © 2011-2022 走看看