从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 ...
随机推荐
- centos7 安装zabbix
一.安装mysql 1.[root@iZ28gvqe4biZ ~]# rpm -Uvh http://dev.mysql.com/get/mysql-community-release-el7-5.n ...
- 爬虫学习06用selenium爬取空间
用selenium爬取空间 from selenium import webdriver from lxml import etree import time pro = webdriver.Chro ...
- OpenCV入门笔记(七) 文字区域的提取
https://blog.csdn.net/huobanjishijian/article/details/63685503 前面我们已经学了一些OpenCV中基本的图片处理的知识,可以拿来做一些小应 ...
- JavaScript笔记 #07# 用js写算法
算法盒子初代(为了提高学习算法的热情...) 效果图: 所有代码放在单个html中: <!DOCTYPE html> <html> <head> <meta ...
- MD5与SHA散列单项加密
MD5 MD5的英文全称是Message Digest Algorithm MD5,译为消息摘要算法第五版,是众多哈希算法中的一种(哈希算法是一种可以将任意长度的输入转化为固定长度输出的算法).因此M ...
- mint-ui之datetime-picker使用
一基本使用<template> <mt-datetime-picker ref="picker" type="time" v-model=&q ...
- PT,PX,DPI
[iOS]查找数组NSArray中是否包含指定的元素 http://blog.csdn.net/zyq527758142/article/details/51278172 Dpi(每平方英寸像素数目) ...
- js的原型prototype究竟是什么?
Javascript也是面向对象的语言,但它是一种基于原型Prototype的语言,而不是基于类的语言.在Javascript中,类和对象看起来没有太多的区别. 1.什么是prototype: fun ...
- Mybatis自增长id处理
目录 1.使用useGenerateKey 2.使用select LAST_INSERT_ID() 3.使用select @@IDENTITY 4.在MySql中模拟Sequence 参考: 1.使用 ...
- Docker 安装Hadoop HDFS命令行操作
网上拉取Docker模板,使用singlarities/hadoop镜像 [root@localhost /]# docker pull singularities/hadoop 查看: [root@ ...