P1040题解

题目链接

这是一道区间DP题,当然你说他是树形DP题也行.因为这道题给的是中序遍历,所以说分清左右子树是很容易的,这为我们使用DP创造了机会. 这里我们假设dp[i][j]表示给出的序列中i到j最大的值.由于是中序遍历,只要这一串是子树那么无论哪个元素是根结点都可以.

因此状态转移方程为

我们用区间DP简单实现即可.这里注意dp[i][i]的值就是a[i].

同时为了输出前序遍历我们记录一下每一段的根节点(root)

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=35;
int n,a[N],dp[N][N],root[N][N];
void work(int l, int r){
	if(l>r) return;
	cout<<root[l][r]<<' ';
	if(l==r) return;
	work(l,root[l][r]-1);
	work(root[l][r]+1,r);
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) root[i][i]=i, dp[i][i-1]=1, dp[i][i]=a[i];
	for(int len=2;len<=n;len++){
		for(int i=1;i+len-1<=n;i++){
			int j=i+len-1;
			dp[i][j]=dp[i+1][j]+a[i], root[i][j]=i;
			for(int k=i+1;k<j;k++){
				if(dp[i][j]<dp[i][k-1]*dp[k+1][j]+a[k]){
					dp[i][j]=dp[i][k-1]*dp[k+1][j]+a[k];
					root[i][j]=k;
				}
			}
		}
	}cout<<dp[1][n]<<endl, work(1,n);
	return 0;
}
相关推荐
Dream it possible!5 分钟前
LeetCode 面试经典 150_二叉搜索树_二叉搜索树中第 K 小的元素(86_230_C++_中等)
c++·leetcode·面试
sin_hielo33 分钟前
leetcode 2872
数据结构·算法·leetcode
dragoooon341 小时前
[优选算法专题八.分治-归并 ——NO.49 翻转对]
算法
AI科技星1 小时前
为什么宇宙无限大?
开发语言·数据结构·经验分享·线性代数·算法
Bona Sun2 小时前
单片机手搓掌上游戏机(十四)—pico运行fc模拟器之电路连接
c语言·c++·单片机·游戏机
Zero-Talent2 小时前
位运算算法
算法
oioihoii2 小时前
性能提升11.4%!C++ Vector的reserve()方法让我大吃一惊
开发语言·c++
不穿格子的程序员2 小时前
从零开始刷算法——双指针-三数之和&接雨水
算法·双指针
小狗爱吃黄桃罐头2 小时前
《C++ Primer Plus》模板类 Template 课本实验
c++
无限进步_3 小时前
C语言数组元素删除算法详解:从基础实现到性能优化
c语言·开发语言·windows·git·算法·github·visual studio