数字三角形——递归、递推、记忆化搜索
数字三角形
描述:
有一个由非负整数组成的三角形,第一行只有一个数,除了最下行之外每个数的左下方和右下方各有一个数。
问题:
从第一行的数开始,每次可以往左下或右下走一格,直到走到最下行,把沿途经过的数全部加起来。如何走才能使得这个和尽量大?
分析:
不难看出此题是一个动态的决策问题:每次有两种选择——左下或右下。如果用回溯法求出所有的可能的路线,就可以从中选出最优的路线。但和往常一样,回溯法的效率太低:一个n层数字三角形的完整路线有2^n条,当n很大时回溯法的速度将让人无法忍受。因此本题讨论用递归,递推及记忆化搜索的方法实现,虽然还有其他的方法,但此时只讨论学习比较相似的这几种方法。
最先想到的是递归实现:
#include "stdio.h"
#define maxn 100
int a[maxn][maxn],n;inline max(int x,int y)
{return x>y?x:y;
}//递归计算实现
int d(int x,int y)
{return a[x][y]+(x==n?0:max(d(x+1,y),d(x+1,y+1)));
}int main()
{while(~scanf("%d",&n)) {int i,j;for(i=1;i<=n;i++){for(j=1;j<=i;j++)scanf("%d",&a[i][j]);}printf("max:%d\n",d(1,1));}return 0;
}
虽然这样做是正确的,但时间效率太低,其原因在于重复计算。
例: 在下列计算中d(3,2)被重复调用
d(2,1) 的计算会调用--> d(3,1) , d(3,2)
d(2,2) 的计算会调用--> d(3,2) , d(3,3)
递推的实现:
#include "stdio.h"
#define maxn 100
int a[maxn][maxn],n;inline max(int x,int y)
{return x>y?x:y;
}//递推实现
int d(int x,int y)
{int d[n][n],i,j; for(j=1;j<=n;j++) d[n][j]=a[n][j];for(i=n-1;i>=1;i--){for(j=1;j<=i;j++)d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]);}return d[x][y];
} int main()
{while(~scanf("%d",&n)) {int i,j;for(i=1;i<=n;i++){for(j=1;j<=i;j++)scanf("%d",&a[i][j]);} printf("max:%d\n",d(1,1)); }return 0;
}
记忆化搜索实现:
#include "stdio.h"
#include "string.h"
#define maxn 100
int a[maxn][maxn],n;
int d[maxn][maxn]; //记忆化搜索所使用的状态记忆数组
inline max(int x,int y)
{return x>y?x:y;
}/*记忆话搜索。程序分成两部分。首先 memset(d,-1,sizeof(d)); 把d全部初始化为-1,
然后编写递归函数:
*/
int distance(int i,int j)
{if(d[i][j]>=0) return d[i][j];return d[i][j]=a[i][j]+(i==n?0:max(distance(i+1,j),distance(i+1,j+1)));
}
/*上述程序依然是递归的,但同时也把计算结果保存在数组d中。题目中说各个数都是非负的,因此
如果已经计算过某个d[i][j],则它应是非负的,这样,只需把所有d初始化为-1,即可通过判断是否
d[i][j]>=0得知是否已经被计算过。
*/ int main()
{while(~scanf("%d",&n)) {int i,j;for(i=1;i<=n;i++){for(j=1;j<=i;j++)scanf("%d",&a[i][j]);}memset(d,-1,sizeof(d)); //状态记忆化数组初始化 printf("max:%d\n",distance(1,1)); }return 0;
}
数字三角形——递归、递推、记忆化搜索相关推荐
- [蓝桥杯][算法提高VIP]夺宝奇兵-递推+记忆化搜索
题目描述 在一座山上,有很多很多珠宝,它们散落在山底通往山顶的每条道路上,不同道路上的珠宝的数目也各不相同.下图为一张藏宝地图: 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 " ...
- 数字三角形(递归/递推)C/C++
递归解法 分析: 这是一道经典的动态规划问题,我们还是从最浅显的算法出发,由浅到深慢慢研究.首先最容易想到的是暴力搜索算法.我们先用一个二维数组map来存放上面的数字三角形,于是有: map[1][1 ...
- Bailian1664 Placing apples【递推+记忆化递归】
1664:Placing apples 总时间限制: 1000ms 内存限制: 65536kB 描述 We are going to place M same apples into N same p ...
- P1464 Function(递归式的记忆化搜索)
传送门 题目描述 对于一个递归函数w(a,b,c)w(a,b,c)w(a,b,c) 如果a≤0a≤0orb≤0b≤0orc≤0c≤0a \le 0a≤0 or b \le 0b≤0 or c \le ...
- POJ1664 放苹果【递推+记忆化递归】
放苹果 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 35209 Accepted: 21792 Description ...
- 动态规划入门——记忆化搜索
文章目录 记忆化搜索 1.数塔问题 2.滑雪 总结 记忆化搜索 1.数塔问题 [动规:递归求解] 递推方程: 不难发现,最后一层的点到最后一层的最大距离即为自己对应的值a[n - 1][y],这个就是 ...
- 经典算法——数字三角形的三种解题方法:递推、记忆化搜索、动态规划
上题目链接: http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/1730.html 递推方法: i ...
- D1 记忆化搜索【递归与递推】递归函数(reduce)
记忆化搜索 防止TLE 考虑如下的3参数递归函数w(a,b,c): 如果a≤0或b≤0或c≤0,则w(a,b,c)=1: 如果a>20或b>20或c>20,则w(a,b,c)=w(2 ...
- UVA - 10253 Series-Parallel Networks(递推式、记忆化搜索写法)
题目:UVA-10253 题目翻译(来自蓝书): 串并联网络有两个端点,一个叫源,一个叫汇,递归定义如下: (1) 一条单独的边是串并联网络. (2) 若G1和G2是串并联网络,把它们的源和源接在一起 ...
最新文章
- tcpdump + wireshark 抓包组合
- vue json 导出 excel
- VTK:Snippets之PointToGlyph
- android 5.0 下载编译
- linux df命令功能,Linux df命令简要介绍
- HDU 6706 huntian oy
- MapReduce分析NCDC 年气象数据最低温度与最高温度
- 【网络编程】中文字符、时间等编码转换
- 【紫书】(UVa12096) The SetStack Computer
- linux 清空history以及记录原理
- Python操作IHTMLDocument2用于自动化测试
- python 根据关键字 切割pdf_用python拆分pdf
- 新版火狐 拖 功能_Firefox 3:新功能,新功能和新功能
- Win10菜单栏卡顿无响应的解决方法
- CTFSHOW-MISC入门
- ElasticSearch全文检索-从零到入门
- html 多余的字省略号,html中把多余文字转化为省略号
- C++ -Pointer指针总结(一)
- greendao的使用
- 【原创】【个人向】CSP-S 2019 爆炸退役记 (已完成)
热门文章
- 在考生文件夹存有JAVA3_注意:下面出现的“考生文件夹”均为%USER%在考生文件夹下存有文件名为J_网考网(Netkao.com)...
- 2022将至,前端程序员们应该一起放个烟花庆祝一下,走起
- 教你读懂Ajax的工作原理
- 教你玩转CSS 伪元素
- 【APICloud系列|14】xcode下载地址
- 如何在 vue-cli v3.0 中使用 SCSS/SASS
- [Electron]仿写一个课堂随机点名小项目
- 安装vue-cli时报错
- 《Effective Java》读书笔记 Item 1:考虑静态工厂方法,而不是构造器
- 【链接】Linux C/C++ 学习路线-已拿腾讯、百度 offer