• 洛谷 P1040 加分二叉树


    题目描述

    设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号。每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下:

    subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数。

    若某个子树为空,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空子树。

    试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree。要求输出;

    (1)tree的最高加分

    (2)tree的前序遍历

    输入输出格式

    输入格式:

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

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

    输出格式:

    第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。

    第2行:n个用空格隔开的整数,为该树的前序遍历。

    输入输出样例

    输入样例#1:
    5
    5 7 1 2 10
    
    输出样例#1:
    145
    3 1 2 4 5
    

    区间DP经典题

    树的中序遍历意味着……

    #include<iostream>
    #include<cstdio>
    #define N 100005
    using namespace std;
    
    struct tree
    {
        int lson,rson,ID;
    };
    tree node[N];
    int visit[N];
    int root;
    int n;
    
    void DFS3(int n)
    {
        if(!n)return;
        DFS3(node[n].lson);
        printf("%d  ",n);
        DFS3(node[n].rson);
    }
    
    void DFS2(int n)
    {
        if(!n)return;
        DFS2(node[n].lson);
        DFS2(node[n].rson);
        printf("%d  ",n);
    }
    
    void DFS1(int n)
    {
        if(!n)return;
        printf("%d  ",n);
        DFS1(node[n].lson);
        DFS1(node[n].rson);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            int lson,rson;
            scanf("%d%d",&lson,&rson);
            node[i].lson=lson;
            node[i].rson=rson;
            visit[lson]=visit[rson]=true;
        }
        for(int i=1;i<=n;++i)
            if(!visit[i])
            {
                root=i;break;
            }
        DFS1(root);
        putchar('
    ');
        DFS2(root);
        putchar('
    ');
        DFS3(root); 
        return 0;
    }

    先序遍历是先访问根节点,然后分别先序遍历左子树和右子树

    中序遍历是先访问左子树,在访问根节点,最后访问右子树

    后序遍历先访问左子树和右子树,最后访问根节点

    这是一个递归的过程,每次递归调用都可以看成是对一颗树的遍历

    直到递归到边界,即空树

    那么,在一个中序遍历中,每一段序列都可以看成是一个递归遍历的子树

    由于只靠一种遍历无法确定树,所以可以有多个不用树的遍历相同

    所以这个题的关键就是找出合法的树得到结果最大

    那么,我们先要枚举每一段序列的根节点,求出最大值

    枚举左边界,枚举右边界,枚举根节点

    这是一个三重循环

    由于要求输出先序遍历

    所以就要记录下答案最大时序列的根节点

    根据这个进行先序遍历

  • 相关阅读:
    Manage It! Part 2 规划和组织项目
    【转载】如何迅速成为Java高手
    Eclipse中最常用的快捷键
    向SQL Server全文索引进军,艰难历程
    数据库函数整理
    ASP.NET MVC简单编程篇(一)
    SQL Server存储过程及高级应用
    定义和赋值的区别 构造函数和拷贝构造函数
    SQL Server 2000
    Coustom web control 自定义控件
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/6913205.html
Copyright © 2020-2023  润新知