• 洛谷P1040 加分二叉树【记忆化搜索】


    题目链接:https://www.luogu.org/problemnew/show/P1040

    题意:

    某一个二叉树的中序遍历是1~n,每个节点有一个分数(正整数)。

    二叉树的分数是左子树分数乘右子树分数加根节点分数,如果子树为空分数是1.

    现在想知道这个二叉树最大的分数是多少,并且输出前序遍历结果。

    思路:

    $f[i][j]$表示$i$~$j$号节点组成的子树的最大分数,为了最后能输出前序遍历结果用$root[i][j]$表示$i~j$号节点组成的子树的根

    枚举根节点,记忆化搜索。

    //#include<bits/stdc++>
    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<stdlib.h>
    #include<queue> 
    #include<map>
    #include<stack>
    #include<set>
    
    #define LL long long
    #define ull unsigned long long
    #define inf 0x3f3f3f3f 
    
    using namespace std;
    int n;
    int sco[35];
    LL f[35][35];
    int root[35][35];
    bool flag = false;
    
    LL dfs(int i, int j)
    {
        if(f[i][j]) return f[i][j];
        if(j < i){
            //root[i][j] = i;
            return 1;
        }
        
        for(int k = i; k <= j; k++){
            LL t = dfs(i, k - 1) * dfs(k + 1, j) + sco[k];
            if(f[i][j] < t){
                root[i][j] = k;    
                f[i][j] = t;
            }
        }
        return f[i][j];
    }
    
    void print(int i, int j){
        if(i > j){
            return;
        }
        if(flag)printf(" ");
        else{
            flag = true;
        }
        printf("%d", root[i][j]);
        print(i, root[i][j] - 1);
        //printf(" %d", root[i][j]);
        print(root[i][j] + 1, j);
        return;
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d", &sco[i]);
            f[i][i] = sco[i];
            root[i][i] = i;
        }
        LL ans = dfs(1, n);
        cout<<ans<<endl;
        print(1, n);
        return 0;    
    } 
  • 相关阅读:
    使用扩展运算符实现数组,对象的深拷贝
    将图片文件转成BASE64格式
    怎么让input默认为0
    两次取反的意义
    css世界一
    Q&H
    .gitignore 中添加.vscode 无效
    百度小程序
    定位元素和opacity
    js 设置元素样式
  • 原文地址:https://www.cnblogs.com/wyboooo/p/10348286.html
Copyright © 2020-2023  润新知