加分二叉树(感觉像是区间dp)
来源:互联网 发布:邓肯数据统计历史排名 编辑:程序博客网 时间:2024/05/22 01:49
【问题描述】
设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点编号。
每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都
有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下:
subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数
若某个子树为空,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空子树。
试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree。要求输出;
(1)tree的最高加分
(2)tree的前序遍历
【输入格式】
第1行:一个整数n(n<30),为节点个数。
第2行:n个用空格隔开的整数,为每个节点的分数(分数<100)。
【输出格式】
第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。
第2行:n个用空格隔开的整数,为该树的前序遍历。
【输入样例】
5
5 7 1 2 10
【输出样例】
145
3 1 2 4 5
- 为什么这种解法是对的?
f[i][j]表示节点i到节点j这一段连续节点所组成的任意子树中所得的最大分数,它可以由f[i][k-1]和f[k+1][j]得到。以此类推,我们讨论了所有二叉树的组成分数,f[i][j]为这所有分数中的最大数,所以是对的。 - 为什么那种解法是错的?
空。 - 为什么这种解法不是最优的?
空 - 证明为什么没有更优的解法。
根节点的左子树上所有节点编号都比根节点编号大(右子树相反)。
首先,想想f[1][n]应该怎么组合才能得到最大分数,我们将1到n每一个节点作为根节点(有n种情况),对于某种情况下i是根节点是,容易知道,左子树最大分数*右子树最大分数+score[i]=以i为根节点的树的最大得分,这样递推下来,每种可能的组合都只讨论了一次,所以是最优解法。
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int f[50][50];int tree[50][50];int node[50][2];void init(){ memset(tree, 0, sizeof(tree)); memset(f, 0, sizeof(f));}int solve(int l,int r){ if (f[l][r]) return f[l][r]; for (int i = l; i <= r; i++) { int x = solve(l, i - 1); int y = solve(i + 1, r); if (x == 0) x = 1; if (y == 0) y = 1; if (x * y + f[i][i] > f[l][r]) { f[l][r] = x*y + f[i][i]; tree[l][r] = i; } } return f[l][r];}void print(int num,int l,int r){ if (tree[l][num - 1]) { printf(" %d", tree[l][num - 1]); print(tree[l][num-1], l, num-1); } if (tree[num + 1][r]) { printf(" %d", tree[num + 1][r]); print(tree[num + 1][r], num + 1, r); }}int main(){ int n; freopen("in.txt", "r", stdin); while (~scanf("%d", &n)) { init(); for (int i = 1; i <= n; i++) { scanf("%d", &f[i][i]); tree[i][i] = i; }; cout << solve(1, n) << endl; printf("%d", tree[1][n]); print(tree[1][n], 1, n); printf("\n"); } return 0;}
1 0
- 加分二叉树(感觉像是区间dp)
- 加分二叉树 区间dp
- Vijos P1100 加分二叉树(区间DP,树形DP)
- 区间dp-洛谷P1040 加分二叉树
- [NOIP2003]区间dp-加分二叉树
- P1040 加分二叉树(区间DP)
- [区间DP]【NOIP2003T3】加分二叉树 题解
- 计蒜客区间dp例题 奇怪的二叉树(NOIP2003加分二叉树)
- 加分二叉树(区间动态规划)
- ACM 106. [NOIP2003] 加分二叉树(区间dp)
- 【基础练习】【区间DP】codevs1090 加分二叉树题解
- NOIP2003-加分二叉树-dp-区间型动态规划
- 加分二叉树(树形dp)
- 加分二叉树(树形dp)
- 【luogu1040】加分二叉树(dp)
- P1040 加分二叉树(树形dp)
- 洛谷P1040 加分二叉树(DP)
- 加分二叉树 树型DP
- (四)索引
- 二分查找(折半查找)
- 第十一周实践项目(4)
- 《电路基础》减法运算放大器
- vim的用法
- 加分二叉树(感觉像是区间dp)
- Android KITKAT 以上实现沉浸式状态栏
- android中bitmap压缩的几种方法的解读
- 第十一周阅读程序(补充)----(3.2)
- Product Studio
- 无废话WCF系列教程网址收藏
- 博客分享
- 拓扑排序
- libcurl在嵌入式设备C 的使用