51nod_1002_数塔取数问题
来源:互联网 发布:淘宝商品管理 编辑:程序博客网 时间:2024/06/08 16:51
题目
原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1002
题目描述:
一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值。
每次只能走到下一层相邻的数上,例如从第3层的6向下走,只能走到第4层的2或9上。
5
8 4
3 6 9
7 2 9 5
例子中的最优方案是:5 + 8 + 6 + 9 = 28
Input:
第1行:N,N为数塔的高度。(2 <= N <= 500)
第2 - N + 1行:每行包括1层数塔的数字,第2行1个数,第3行2个数……第k+1行k个数。
数与数之间用空格分隔(0 <= A[i] <= 105) 。
Output:
输出最大值
解题思路
自底向上
从上往下走,只有两种选择,所以所有可能的路的条数可以用一个二叉树来表示。如下图:
图1 路径的所有可能数
从图1很容易的能够看出来,要想整个路径达到最大,就要5加上它左右节点到叶子节点较大的一个,
即 res = 5 + max(left, right)。由此我们就可以递归地求解。
res f(root) { if (leaf) return leaf; else return root + max(left, right);}
但是我们可以发现,在整个递归过程中,重复计算了很多节点。如图6中,节点6出现了
两次,层数越多,重复计算的就越多,会导致指数级的时间复杂度。
我们可以用额外的空间来保存已经计算过的子树的最大值,当再次访问到相同的节点时,
就不用继续递归,直接返回值。
res fun(root) { if (leaf) return leaf; if (root in the table) return max of root; else { table[root] = root + max(left, right); return table[root]; }}
自顶向下
这种思路就是从上往下,计算出顶部到达某一层每个节点的路径长度,保存到数组中,
然后以此层路径长度计算下一层路径长度,直到最底层。最后顶层到所有叶子节点的
最长路径都计算出来,只需找到其中的最大值就行。
代码
自底向上
#include <stdio.h>#include <stdlib.h>typedef int DataType; DataType data[505][505];//原数据DataType table[505][505];//记录计算的值int n = 0;DataType max(DataType a, DataType b) { return a > b ? a : b;}DataType dp(int i, int j) { if (i > n) { return 0; } if (table[i][j] != 0) { return table[i][j]; } else { table[i][j] = max(dp(i + 1, j), dp(i + 1, j + 1)) + data[i][j]; return table[i][j]; }}int main() { scanf("%d", &n); int i, j; for(i = 2;i <= n;i++) { for(j = 1;j <= i;j++) { scanf("%d", &data[i][j]); } } DataType res = dp(0, 0); printf("%d\n", res); return 0;}
自顶向下
#include <stdio.h>#include <stdlib.h>typedef int DataType; DataType max(DataType a, DataType b) { return a > b ? a : b;}DataType dp[505];int main() { int n; scanf("%d", &n); scanf("%d", dp + 1);//第一层 int i, j, x, m; for (i = 2;i <= n;i++) { DataType a = 0; for (j = 1;j <= i;j++) { scanf("%d", &x); m = max(dp[j], dp[j-1]) + x;// 根据上一层计算到达x节点的最大值 dp[j-1] = a;// 更新dp[j-1],此时dp[j-1]保存的是当前层对应节点的最大值 a = m; } dp[i] = a; //当前层的最后一个节点 } // 遍历保存的值,找出最大 DataType res = dp[1]; for (i = 2;i <= n;i++) { if (res < dp[i]) { res = dp[i]; } } printf("%d\n", res); return 0;}
- 51nod_1002_数塔取数问题
- 51nod1002 数塔取数问题
- 51nod1002 数塔取数问题
- 51Nod 1002 数塔取数问题
- 51 nod 1002 数塔取数问题
- 51nod 1002 数塔取数问题
- 51nod:1002 数塔取数问题
- 51nod 1002 数塔取数问题
- 51nod-【1002 数塔取数问题】
- 51nod 1002 数塔取数问题
- 51Nod 1002 数塔取数问题
- 51nod 1002 数塔取数问题
- 1002 数塔取数问题 51NOD
- 51nod 1002 数塔取数问题
- 51nod 1002 数塔取数问题
- 51Nod 1002 数塔取数问题
- 【51Nod】1002 数塔取数问题
- 51Nod--1002 数塔取数问题
- more effective C++
- 救基友记2
- (C语言)高精度减法
- 17滴滴春招大题
- Sass入门(一)
- 51nod_1002_数塔取数问题
- [背包DP || 多项式] 51Nod 1597 有限背包计数问题
- 枚举算法
- web2——景点主页
- 交叉验证(cross_validation)
- POJ 1029 False coin 笔记 模拟
- dfs-hdu2782
- Spring Boot集成CKFinder-优化
- 剑指offer--面试题13:在O(1)时间删除链表结点