加分二叉树[记搜]

题目描述

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

(1)treetree的最高加分

(2)treetree的前序遍历

输入格式

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

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

输出格式

第1行:1个整数,为最高加分(Ans≤4,000,000,000)。

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

输入输出样例

输入

5
5 7 1 2 10

输出

145
3 1 2 4 5

f i j f_{ij} fij为i到j的最大加分子树,那么我们可以枚举顶点k 有转移 f i j = f i k − 1 ∗ f k + 1 r + a [ k ] f_{ij} = f_{ik-1} * f_{k+1r} +a[k] fij=fik1fk+1r+a[k]
每次更新的时候我们记录枚举出的i-j的根,最后根据遍历顺序输出。

#include<bits/stdc++.h>

#define ll long long
#define MAXN 5000100
#define N 1001
#define INF 0x3f3f3f3f
#define gtc() getchar()

using namespace std;

template <class T>
inline void read(T &s){
	s = 0; T w = 1, ch = gtc();
	while(!isdigit(ch)){if(ch == '-') w = -1; ch = gtc();}
	while(isdigit(ch)){s = s * 10 + ch - '0'; ch = gtc();}
	s *= w;
}

template <class T>
inline void write(T x){
    if(x < 0) putchar('-'), x = -x;
	if(x > 9) write(x/10);
    putchar(x % 10 + '0');
}

int n;
ll a[50];
ll f[100][100];
ll root[100][100];

int dfs(int l, int r){
//	puts("1");
//	printf("%d %d\n", l, r); 
	if(f[l][r] > 0) return f[l][r];
	if(l == r) return a[l];
	if(r < l) return 1;
	for(int i = l; i <= r; ++i){
		int x = dfs(l, i-1) * dfs(i+1, r) + f[i][i];
		if(x > f[l][r]) f[l][r] = x, root[l][r] = i;
	}
	return f[l][r];
}

void out(int l, int r){
	if(r < l) return ;
	if(l == r){
		printf("%d ", l); return ;
	}
	printf("%d ", root[l][r]);
	out(l, root[l][r]-1); out(root[l][r]+1, r);
}

int main()
{
	memset(f, 0, sizeof(f));
	read(n);
	for(int i = 1; i <= n; ++i) read(a[i]), f[i][i] = a[i];
	
	cout << dfs(1, n) << endl;	
	out(1, n);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIGBIGPPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值