蒟蒻的思路

071maozihan 2022-04-24 16:21:20 2022-04-24 16:21:34 11 返回题目

题意概括

————————————————————

有一个n个节点二叉树,每个节点都有一个价值a[i],且这棵树的中序遍历为 1~n

这个树中的任意一个子树(包含这棵树本身)的价值有以下的定义:

子树的价值 = 根节点的价值 + 左子树的价值 * 右子树的价值

问这棵树的最大价值为多少?并且要求求出这棵树的先序遍历

题目思路

————————————————————

问这棵树的最大价值?

这个问题其实可以进行分解:

一棵树的最大价值 = 左子树的最大价值*右子树的最大价值 + 根节点的价值

同理:这棵树的左子树的最大价值也可以分解成类似的问题

这样一来我们可以把问题规模不断地缩小……

那么,缩小到什么程度呢?

那废话,肯定是分无可分的时候啦~~~~~~

代码实现

——————————————————————


#include<bits/stdc++.h>
#define int long long
using namespace std;
const long long maxn=35;
int n;
int a[maxn];
int dp[maxn][maxn],t[maxn][maxn],cnt; // dp用来记录l~r的最大值,t用来记录l~r的根节点
void dfs(int l,int r) //追溯 l~r 的根节点
{
	if(l > r)return ;
	cout<<t[l][r]<<" ";
	dfs(l,t[l][r]-1);
	dfs(t[l][r]+1,r);
}
int DFS(int l,int r)
{
	if(l > r) return 1;//此时已经分无可分了,那最大值就是1
	if(l == r) {
		t[l][r] = l;//相等的时候根节点就是本身
		return a[l]; //相等时最大值也是本身
	}
	if(dp[l][r] != -1)return dp[l][r]; //记忆化搜索
	int ans=INT_MIN,id;
	for(int i=l;i<=r;i++){ // 枚举根节点 将树分为 l~i-1 (左子树), i(根节点) ,i+1 ~ r(右子树)
		int tmp=DFS(l,i-1)*DFS(i+1,r)+a[i];
		if(ans < tmp){
			ans=tmp;
			id = i;
		}	
	}
	t[l][r] = id;//记录根节点
	return dp[l][r] = ans;
}
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		for(int j=1;j<=n;j++){
			dp[i][j] = -1; //初始化
		}
	}
	cout<<DFS(1,n)<<endl; //输出问题最大值
	dfs(1,n); //输出前序遍历
	return 0;
}

{{ vote && vote.total.up }}