zoukankan      html  css  js  c++  java
  • luoguP1040 [NOIP2003]加分二叉树

    题目链接

    看了y总的视频然后自己推了一遍

    做法就是区间DP

    • 几点需要注意的:
      千万别忘了开long long(因为题目中说了Ans <= 4,000,000,000)
      边界问题需要仔细考虑
      记录答案的先序排列和输出值得思考

    贴一下代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    
    const int N = 35;
    ll n, w[N], f[N][N], g[N][N];
    
    void print(int l, int r) {
    	if(l > n || r < 1 || r < l) return;
    	int root = g[l][r];
    	if(l == r){//叶子节点,因为没有子树,输出后直接return
    		cout << root << ' ';
    		return;
    	}
    	cout << root << ' ';//不是叶子节点,输出当前区间的根节点
    	print(l, root - 1);//递归输出左子树
    	print(root + 1, r);//递归输出右子树
    }
    
    signed main() {
    	cin >> n;
    	for(int i = 1; i <= n ; i ++)
    		cin >> w[i];
    	
    	for(int i = 1; i <= n ; i ++) {//一定要记得初始化
    		f[i][i] = w[i];
    		g[i][i] = i;
    	}
    	for(int len = 2; len <= n ; len ++)//枚举区间长度
    		for(int l = 1; l + len - 1 <= n ; l ++){//枚举左端点
    			int r = l + len - 1;//计算右端点
    			for(int k = l; k <= r; k ++) {//枚举每个区间的根节点
    				ll left = k == l ? 1 : f[l][k-1];//如果没有左子树,左子树的价值就是1
    				ll right = k == r ? 1 : f[k+1][r];//如果没有右子树,右子树的价值就是1
    				ll score = left * right + w[k];//计算总价值
    				if(f[l][r] < score) {//用if更新答案,而不用max,方便记录,这里是`<`而不是`<=`因为先序遍历如果有多种要按字典序输出(luogu上没说这个条件,但是AcWing上说了)
    					f[l][r] = score;//更新答案
    					g[l][r] = k;//记录区间l~r的根节点
    				}
    			}
    		}
    	cout << f[1][n] << endl;
    	print(1, n);	
    	return 0;
    }
    

    要是还不懂就好好看看那两张图(两张内容是一样的)。

  • 相关阅读:
    ajax_基础1
    省市数据库脚本TblArea.
    c#中怎么使用dos命
    Lambda表达式
    面试收录
    .Net牛逼程序猿要懂得
    Web.config 配置文件
    sql 查询所有数据库、表名、表字段总结
    Json在net与页面之间的传递
    『转』SAP统驭科目解释
  • 原文地址:https://www.cnblogs.com/sjzez-llb/p/13930805.html
Copyright © 2011-2022 走看看