Tyvj1073
来源:互联网 发布:mac project软件 编辑:程序博客网 时间:2024/06/16 08:18
题目链接
分析:
我这个zz,老是不看题
总是因为做过一道题而跳过题目,所以忽视了很多条件
这道题,一开始我认为是随意n个点
求任一符合要求的前序遍历
想了好久都觉得很困难
于是又读了一遍题目
发现题目规定二叉树的中序遍历是1,2,3,4,…,n
如果标算太难请坚定信念
不如回头再看一眼题面 ——–Menci
一道区间dp
已知中序遍历,那么一棵子树的所有节点一定在序列中的一个连续区间内
根节点一定在序列中
我们可以枚举根节点
f[i][j]表示i~j的节点是一棵子树
根节点是k
f[i][j]=max{f[i][k-1]*f[k+1][j]+a[k]}
至于最后的输出,我们只要再用一个g数组记录一下f[i][j]最优情况下的根节点是哪个
最后递归输出就好了
附样例图
tip
好好读题
不要手残
这里写代码片#include<cstdio>#include<cstring>#include<iostream>#define ll long longusing namespace std;const int N=35;ll f[N][N];ll a[N];int g[N][N];int n;void print(int l,int r){ if (l>r) return; if (l==r) { printf("%d ",l); return; } printf("%d ",g[l][r]); print(l,g[l][r]-1); print(g[l][r]+1,r);}int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lld",&a[i]); for (int i=1;i<=n;i++) f[i][i]=a[i]; int i,j,k; for (i=n-1;i>=1;i--) for (j=i+1;j<=n;j++) for (k=i;k<=j;k++) { if (k==i) if (f[k+1][j]+a[k]>f[i][j]){ f[i][j]=f[k+1][j]+a[k]; //无左儿子 g[i][j]=k; //根节点 } if (k==j) if (f[i][k-1]+a[k]>f[i][j]){ f[i][j]=f[i][k-1]+a[k]; //无右儿子 g[i][j]=k; } if (k!=i&&k!=j) if (f[i][k-1]*f[k+1][j]+a[k]>f[i][j]){ f[i][j]=f[i][k-1]*f[k+1][j]+a[k]; g[i][j]=k; } } printf("%lld\n",f[1][n]); print(1,n); return 0;}