FZU1004-Number Triangle经典动归题,核心思路及代码优化
Accept: 2230 Submit: 5895
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
Consider the number triangle shown below. Write a program that calculates the highest sum of numbers that can be passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right.
|
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
|
In the sample above, the route from 7 to 3 to 8 to 7 to 5 produces the highest sum: 30.
Input
Output
Sample Input
Sample Output
很明显的一道动归题,类似于求最大路径,方法有很多,搜索啊,递归啊,,,但用动归是最简单的,动归思路有两种:
1:
用二维数组存放数字三角形;
D( r, j) : 第r行第 j 个数字(r,j从1 开始算)
MaxSum(r, j) : 从D(r,j)到底边的各条路径中最佳路径的数字之和,问题是就求MaxSum(1,1);
典型的递归问题
D(r, j)出发,下一步只能走D(r+1,j)或者D(r+1, j+1)。故对于N行的三角形:
if ( r == N)
MaxSum(r,j) = D(r,j)
else
MaxSum( r, j) = Max{ MaxSum(r+1,j), MaxSum(r+1,j+1) } + D(r,j);
2: 如果每算出一个MaxSum(r,j)就保存起来,下次用到其值的时候直接取用,则可免去重复计算。
那么可以用 O(n2)时间完成计算。因为三角形的数字总数是 n(n+1)/2;这时,递归转化为递推;
下面呈现两种思路代码:
1:超时代码:
#include <iostream>
#include <algorithm>
#define MAX 101
using namespace std;
int D[MAX][MAX];
int n;
int MaxSum(int i, int j){
if(i==n)
return D[i][j];
int x = MaxSum(i+,j);
int y = MaxSum(i+,j+);
return max(x,y)+D[i][j];
}
int main(){
int i,j;
cin >> n;
for(i=;i<=n;i++)
for(j=;j<=i;j++)
cin >> D[i][j];
cout << MaxSum(,) << endl;
}
如果采用递规的方法,深度遍历每条路径,存在大量重复计算。则时间复杂度为 2n, 对于 n = 100行,肯定超时。
2:记忆递归
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX 101
int D[MAX][MAX]; int n;
int maxSum[MAX][MAX];
int MaxSum(int i, int j){
if( maxSum[i][j] != - )
return maxSum[i][j];
if(i==n) maxSum[i][j] = D[i][j];
else {
int x = MaxSum(i+,j);
int y = MaxSum(i+,j+);
maxSum[i][j] = max(x,y)+ D[i][j];
}
return maxSum[i][j];
}
int main(){
int i,j;
cin >> n;
for(i=;i<=n;i++)
for(j=;j<=i;j++) {
cin >> D[i][j];
maxSum[i][j] = -;
}
cout << MaxSum(,) << endl;
}
3:
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX 101
int D[MAX][MAX]; int n;
int maxSum[MAX][MAX];
int main() {
int i,j;
cin >> n;
for(i=;i<=n;i++)
for(j=;j<=i;j++)
cin >> D[i][j];
for( int i = ;i <= n; ++ i )
maxSum[n][i] = D[n][i];
for( int i = n-; i>= ; --i )
for( int j = ; j <= i; ++j )
maxSum[i][j] = max(maxSum[i+][j],maxSum[i+][j+]) + D[i][j]
cout << maxSum[][] << endl;
}
人人为我”递推型动归程序
4:当然了,3中的代码也可以空间优化,从下往上找
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX 101
int D[MAX][MAX];
int n; int * maxSum;
int main(){
int i,j;
cin >> n;
for(i=;i<=n;i++)
for(j=;j<=i;j++)
cin >> D[i][j];
maxSum = D[n]; //maxSum指向第n行
for( int i = n-; i>= ; --i )
for( int j = ; j <= i; ++j )
maxSum[j] = max(maxSum[j],maxSum[j+]) + D[i][j];
cout << maxSum[] << endl;
}
如果看不懂简单手推模拟一遍你就明白了,不难。。和3中代码类似,只是将二维转化为一维了;
FZU1004-Number Triangle经典动归题,核心思路及代码优化的更多相关文章
- 6581 Number Triangle
6581 Number Triangle 时间限制:500MS 内存限制:1000K提交次数:57 通过次数:47 题型: 编程题 语言: G++;GCC Description 7 3 8 8 ...
- JAVA经典算法40题及解答
JAVA经典算法40题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分 ...
- JAVA经典算法40题
1: JAVA经典算法40题 2: [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 3 ...
- JAVA经典算法40题(原题+分析)之分析
JAVA经典算法40题(下) [程序1] 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: ...
- JAVA经典算法50题(转)
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/51097928 JAVA经典算法50题 [程序1] 题目:古典问题:有一对兔子, ...
- JAVA经典算法40题面向过程
JAVA经典算法40题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分 ...
- java经典算法40题-附带解决代码
前一段时间工作比较闲,每天没有代码敲的日子有点无聊,于是为了保证自己的编程逻辑力的日常清醒,故百度了一些经典的java算法,然后自己思考编程解决问题,虽然那些东西比较基础了,但是有些题目小编看到了也是 ...
- UVA 674 Coin Change 换硬币 经典dp入门题
题意:有1,5,10,25,50五种硬币,给出一个数字,问又几种凑钱的方式能凑出这个数. 经典的dp题...可以递推也可以记忆化搜索... 我个人比较喜欢记忆化搜索,递推不是很熟练. 记忆化搜索:很白 ...
- JAVA经典算法40题(原题+分析)之原题
JAVA经典算法40题(上) [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? [程 ...
随机推荐
- Xml文档数据提取到Excel表中
近期,财务一位同事,吐槽:<某XX开票软件>导出数据文档只有Xml格式,竟然没有Excel文档,工作起来非常不方便,希望我想想办法.上图: 需求分析:Xml数据----> 提取到Da ...
- iframe及其引出的页面跳转问题
前提:在前一段的工作中碰到了一些页面跳转,子页面跳到父页面上的等等问题,当时页面总是跳不对,或者跳错,要不就是不需要重新打开窗口,却又重新打开一个了,特此搜寻网上各大博客论坛,加上项目经验整理一篇文章 ...
- FPGA开发中的脚本语言
多数FPGA开发者都习惯图形化界面(GUI).GUI方式简单易学,为小项目提供了一键式流程.然而,随着FPGA项目越来越复杂,在很多情况下GUI工具就阻碍了工作效率.因为GUI工具不能对整个开发过程提 ...
- 下载JSTL方法
第一步:访问 http://www.apache.org/dist/ 第二步:点击jakarta
- Java Web MVC实例
开发环境 Eclipse Java EE IDE for Web Developers. Version: Luna Service Release 2 (4.4.2) tomcat:7.0 数据库: ...
- Python学前基础知识
Python基础计算机常识:硬件性能:CPU.内存输入设备:鼠标.键盘外部存储设备:硬盘输出设备;显示器.打印机(不算自带)通讯设备:无线网卡----------------------------- ...
- Python 使用random模块生成随机数
需要先导入 random 模块,然后通过 random 静态对象调用该一些方法. random() 函数中常见的方法如下: # coding: utf-8 # Team : Quality Mana ...
- 原生JS--各种兼容性写法总结
<script> var oEvent = evt || event; ========================================================== ...
- 递推(三):POJ中的三道递推例题POJ 1664、POJ 2247和POJ 1338
[例9]放苹果(POJ 1664) Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. In ...
- docker 容器的网络
容器的网络模式 bridge -net=bridge 默认网络.docker启动后创建一个docker0网桥,默认创建的容器也添加到这个网桥 [root@localhost ~]# ip a 1: l ...