[Problem solution] Luogu P1040 [NOIP2003] Adding a binary tree

Go to: My own blog

topic

Luogu P1040 Plus Binary Tree

answer

In the middle-order traversal sequence, each subinterval corresponds to a tree. If the root node is determined, then the left subtree of the node is the left subtree and the right subtree is the right subtree. The interval dp can be used.

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=35;
int n;
int rt[maxn][maxn]; //记录区间[l,r]构成的子树的根节点 
ll f[maxn][maxn],sc[maxn]; //sc[]表示分数 
void dfs(int l,int r) //前序遍历 
{
	printf("%d ",rt[l][r]);
	if(rt[l][r]>l) dfs(l,rt[l][r]-1);
	if(rt[l][r]<r) dfs(rt[l][r]+1,r);
}
inline void dp()
{
	for(int i=1;i<=n;i++) f[i][i]=sc[i],rt[i][i]=i; //初始化 
	for(int len=2;len<=n;len++)
	{
		for(int l=1; ;l++)
		{
			int r=l+len-1; if(r>n) break;
			if(sc[l]+f[l+1][r]>f[l][r]) f[l][r]=sc[l]+f[l+1][r],rt[l][r]=l; //根节点为l的特殊情况
			if(sc[r]+f[l][r-1]>f[l][r]) f[l][r]=sc[r]+f[l][r-1],rt[l][r]=r; //根节点为r的特殊情况 
			//k为[l,r]这棵子树的根节点 
			for(int k=l+1;k<=r-1;k++) if(sc[k]+f[l][k-1]*f[k+1][r]>f[l][r]) f[l][r]=sc[k]+f[l][k-1]*f[k+1][r],rt[l][r]=k;
		}
	}
	printf("%lld\n",f[1][n]);
}

int main()
{
	scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&sc[i]);
	dp(); dfs(1,n); 
	
	return 0;
}

Guess you like

Origin blog.csdn.net/zjgmartin/article/details/108565110