从DFS到记忆化DFS到动态规划
什么是动态规划?
动态规划(Dynamic Programming)是通过组合子问题的解来解决问题的。动态规划是用于求解包含重叠子问题的最优化问题的方法。其基本思想是,将原问题分解为相似的子问题。在求解的过程中通过子问题的解求出原问题的解。
动态规划的分类:
1. 线性规划:拦截导弹,合唱队形,挖地雷等。
2. 区域规划:石子合并,加分二叉树,统计单词个数等。
3. 树形动规:贪吃的九头龙,二分查找树,聚会的欢乐等。
4. 背包问题:01背包问题,完全背包问题,分组背包问题,装箱问题,挤牛奶等
5. 除此之外还有插头DP,按位DP,状态压缩DP等等。
入门题目:数字三角形
题目描述:给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于
每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
注意:路径上的每一步只能从一个数走到下一层上和它最近的左边的那个数或者右边的那个数。
如:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
分析一下为什么不能使用贪心算法,即每一次走都走下一行的两个数值较大的。因为有可能在某一步的时候数值小没走到,但是该路径下面有较大的数值,就不会走到,就得不到最大的值。
1.朴素DFS搜索算法
可以采用朴素的深度优先搜索算法,即朴素DFS。每一次走都分为两步,第一步求出走下一步时走的最大值,然后加上此步的数值。
int dfs(int x,int y) //表示从第x行,第y个数往下走可以得到的最大价值和,dfs(0,0)即为本题解。
{
if(x > numCount - )
return ;
return max(dfs(x+,y),dfs(x+,y+)) + num[x][y];
}
完整的代码示例为:
#include
using namespace std;
int num[][] = {,,,,,
,,,,,
,,,,,
,,,,,
,,,,};
int numCount = ;
int dfs(int x,int y)
{
if(x > numCount - )
return ;
return max(dfs(x+,y),dfs(x+,y+)) + num[x][y];
}
int main()
{
int maxsum = ;
maxsum = dfs(,);
cout<<maxsum<<endl;
return ;
}
这个算法效率极低,为什么呢?因为其中有大量的重复计算。通常递归都会有大量的重复计算。
2.DFS+记忆化搜索方法
针对于上述DFS算法的重复计算,我们可以先将dfs(x,y)的结果保存起来,等到下次需要时,直接使用。这就是记忆化搜索。
int dfs(int x,int y)
{
if(x > numCount - )
return ;
if(result[x][y] != -)
return result[x][y];
return result[x][y] = max(dfs(x+,y),dfs(x+,y+)) + num[x][y];
}
完整的代码示例为:
#include
using namespace std;
int num[][] = {,,,,,
,,,,,
,,,,,
,,,,,
,,,,};
int numCount = ;
int result[][];
int dfs(int x,int y)
{
if(x > numCount - )
return ;
if(result[x][y] != -)
return result[x][y];
return result[x][y] = max(dfs(x+,y),dfs(x+,y+)) + num[x][y];
}
int main()
{
for(int i = ;i < ;i++)
for(int j = ; j < ;j++)
result[i][j] = -;
int maxsum = ;
maxsum = dfs(,);
cout<<maxsum<<endl;
return ;
}
不论是DFS还是记忆化DFS都是基于递归的思想进行计算。总结一下实际操作的特点。
(1)搜索的参数只有(x,y),每一对(x,y)确定一个状态。
(2)搜搜的转移是从(x+1,y)和(x+1,y+1)到(x,y)的,意思就是我们通过(x+1,y)和(x+1,y+1)的解去求(x,y)。
于是,设想:如果不用DFS,直接用数组保存状态,在状态与状态之间实现转移。
for(int i = numCount - ; i >= ; i--)
for(int j = ;j <= i; j++)
result[i][j] = max(result[i+][j],result[i+][j+]) + num[i][j];
完整的程序示例为:
#include
using namespace std;
int num[][] = {,,,,,
,,,,,
,,,,,
,,,,,
,,,,};
int numCount = ;
int result[][];
int main()
{
for(int i = ;i < ;i++)
for(int j = ; j < ;j++)
result[i][j] = ;
for(int i = numCount - ; i >= ; i--)
for(int j = ;j <= i; j++)
result[i][j] = max(result[i+][j],result[i+][j+]) + num[i][j];
int maxsum = ;
maxsum = result[][];
cout<<maxsum<<endl;
return ;
}
总结:搜索的参数只有(x,y)。每一对(x,y)确定一个状态。我们通过(x+1,y)和(x+1,y+1)的解去求(x,y),于是我们可以设计出状态并明确状态的转移,从而写出状态转移方程。这就是动态规划!!!!
摘自:http://blog.sina.com.cn/s/blog_8eac84090102vt0y.html
作者:慕雪
从DFS到记忆化DFS到动态规划的更多相关文章
- poj 1088 动态规划+dfs(记忆化搜索)
滑雪 Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Description Mi ...
- 【poj3252】 Round Numbers (数位DP+记忆化DFS)
题目大意:给你一个区间$[l,r]$,求在该区间内有多少整数在二进制下$0$的数量$≥1$的数量.数据范围$1≤l,r≤2*10^{9}$. 第一次用记忆化dfs写数位dp,感觉神清气爽~(原谅我这个 ...
- HDU1978How Many Ways 记忆化dfs+dp
/*记忆化dfs+dp dp[i][j]代表达到这个点的所有路的条数,那么所有到达终点的路的总数就是这dp[1][1]加上所有他所能到达的点的 所有路的总数 */ #include<stdio. ...
- 滑雪 矩阵中的最长上升路径 /// 记忆化DFS || DP oj22919
大致题意: Description 难怪Michael喜欢滑雪,因为滑雪确实很刺激.为了获得加速度,滑雪道必须向下倾斜,而且当滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一 ...
- 【BZOJ1048】分割矩阵(记忆化搜索,动态规划)
[BZOJ1048]分割矩阵(记忆化搜索,动态规划) 题面 BZOJ 洛谷 题解 一个很简单的\(dp\),写成记忆化搜索的形式的挺不错的. #include<iostream> #inc ...
- *HDU1142 最短路+记忆化dfs
A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav ...
- 最大联通子数组之和(dfs,记忆化搜索,状态压缩)
最大联通子数组,这次的题目,我采用的方法为dfs搜索,按照已经取到的数v[][],来进行搜索过程的状态转移,每次对v[][]中标记为1的所有元素依次取其相邻的未被标记为1的元素,将其标记为1,然而,这 ...
- HDU ACM 1078 FatMouse and Cheese 记忆化+DFS
题意:FatMouse在一个N*N方格上找吃的,每一个点(x,y)有一些吃的,FatMouse从(0,0)的出发去找吃的.每次最多走k步,他走过的位置能够吃掉吃的.保证吃的数量在0-100.规定他仅仅 ...
- 洛谷 P3953 逛公园【spfa+记忆化dfs+bfs】
spfa预处理出最短路数组dis,然后反向建边bfs出ok[u]表示u能到n点 然后发现有0环的话时候有inf解的,先dfs找0环判断即可 然后dfs,设状态f[u][v]为到u点,还可以跑最短路+v ...
随机推荐
- Python进阶【第七篇】文件处理
一.文件操作 在Python中,文件读写是最常见的操作.对文件的操作为: #1. 打开文件,得到文件句柄并赋值给一个变量 f=open('a.txt','r',encoding='utf-8') #默 ...
- springMVC之一(页面<--->控制器 互相传值,转发和重定向)
#页面--->控制器1.request:不建议使用2.使用属性传值(建议使用)@RequestParam("name") String username3.使用Bean对象传 ...
- Hbuilder安装
---恢复内容开始--- ---恢复内容结束---
- Google翻译实现
https://blog.csdn.net/yingshukun/article/details/53470424 Google翻译实现
- mysql union 和 left join 结合查询用法
union 和 left join 结合查询用法 SELECT u.nickname,z.group_comming_type,z.id,z.user_id,z.title,z.create_time ...
- sublime text3 批量查找替换文件夹或项目中的字符
1.点击左上角的“菜单”,在弹出的菜单中选择“打开文件夹”. 2.在文件夹上右击,选择“在文件夹中查找”选项 3.之后会软件底部会弹出对话框,分别输入要查找的内容和替换的内容,最后点击替换按钮 4.再 ...
- csrf_token(跨站伪造)
Django跨站请求伪造 跨站请求伪造(Cross-site request forgery),也被称为one-click attack或者session riding,通常缩写为CSRF或者XSR ...
- Mac安装HomeBridge适配小米Homekit报错:module未找到解决
Mac安装HomeBridge适配小米Homekit报错:module未找到 具体错误是: module.js:471 throw err; balabalal...... 问了一圈,终于解决,但是又 ...
- HDU 5929 Basic Data Structure(模拟 + 乱搞)题解
题意:给定一种二进制操作nand,为 0 nand 0 = 10 nand 1 = 1 1 nand 0 = 1 1 nand 1 = 0 现在要你模拟一个队列,实现PUSH x 往队头塞入x,POP ...
- JPA原理与实践、多数据源配置
参考博客: https://segmentfault.com/a/1190000015047290?utm_source=Weibo&utm_medium=shareLink&utm_ ...