提高组打卡day3—— AcWing 479. 加分二叉树

【题目描述】
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
【思路】
状态表示:f[i][j]表示中序遍历是w[i]到w[j]的所有二叉树的得分的最大值。
状态计算:f[i][j] = max(f[i][k - 1] * f[k + 1][j] + w[k]),即将f[i][j]表示的二叉树 集合按根节点分类,当根节点在k取最大得分时为 f[i][k - 1] * f[k + 1][j] + w[k]。f[[i]
[j]就是遍历所有k取得的最大。

时间复杂度分析:状态数为N * N,每个状态计算量为O(N),所以时间复杂度为O(N^3)

import  java.io.*;
import java.lang.Math;
public class Main{
    static int N = 35;
    static int w[] = new int [N]; //记录节点分数
    static int f[][] =  new int[N][N];//f[i][j]记录区间[i,j]的最大分数值
    static int root[][] = new int[N][N];//记录f[i][j]所对应的根
    public static void dfs(int l, int r){
        if(l > r ) return ;
        int t = root[l][r];//根
        System.out.print(t+" ");
        dfs(l, t -1);
        dfs(t + 1, r);
    }
    public static void main(String aregs[])throws Exception{
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(bf.readLine());
        String s[] = bf.readLine().split(" ");
        for(int i = 1; i <= n; i++) w[i] = Integer.parseInt(s[i - 1]);
        //区间dp
        for(int len = 1; len <= n; len ++)
            for(int l = 1; l + len - 1 <= n; l++){
                int r = l + len -1;
                //枚举[l,r]区间的根节点
                for(int k = l; k <= r; k++){
                    //计算左子树和右子树
                    int left = (k == l? 1 : f[l][k - 1]);
                    int right = (k == r? 1 : f[k + 1][r]);
                    int score = left * right + w[k];
                    
                    //叶子结点
                    if( l == r) score = w[k];
                    if( f[l][r] < score){
                        //更新分数和根节点
                        f[l][r] = score;
                        root [l][r] = k;
                    }
                }
            }
               
        System.out.println(f[1][n]);
        dfs(1, n);
        
       
           
        
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值