什么是动态规划?

动态规划(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到动态规划的更多相关文章

  1. poj 1088 动态规划+dfs(记忆化搜索)

    滑雪 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u   Description Mi ...

  2. 【poj3252】 Round Numbers (数位DP+记忆化DFS)

    题目大意:给你一个区间$[l,r]$,求在该区间内有多少整数在二进制下$0$的数量$≥1$的数量.数据范围$1≤l,r≤2*10^{9}$. 第一次用记忆化dfs写数位dp,感觉神清气爽~(原谅我这个 ...

  3. HDU1978How Many Ways 记忆化dfs+dp

    /*记忆化dfs+dp dp[i][j]代表达到这个点的所有路的条数,那么所有到达终点的路的总数就是这dp[1][1]加上所有他所能到达的点的 所有路的总数 */ #include<stdio. ...

  4. 滑雪 矩阵中的最长上升路径 /// 记忆化DFS || DP oj22919

    大致题意: Description 难怪Michael喜欢滑雪,因为滑雪确实很刺激.为了获得加速度,滑雪道必须向下倾斜,而且当滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一 ...

  5. 【BZOJ1048】分割矩阵(记忆化搜索,动态规划)

    [BZOJ1048]分割矩阵(记忆化搜索,动态规划) 题面 BZOJ 洛谷 题解 一个很简单的\(dp\),写成记忆化搜索的形式的挺不错的. #include<iostream> #inc ...

  6. *HDU1142 最短路+记忆化dfs

    A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Jav ...

  7. 最大联通子数组之和(dfs,记忆化搜索,状态压缩)

    最大联通子数组,这次的题目,我采用的方法为dfs搜索,按照已经取到的数v[][],来进行搜索过程的状态转移,每次对v[][]中标记为1的所有元素依次取其相邻的未被标记为1的元素,将其标记为1,然而,这 ...

  8. HDU ACM 1078 FatMouse and Cheese 记忆化+DFS

    题意:FatMouse在一个N*N方格上找吃的,每一个点(x,y)有一些吃的,FatMouse从(0,0)的出发去找吃的.每次最多走k步,他走过的位置能够吃掉吃的.保证吃的数量在0-100.规定他仅仅 ...

  9. 洛谷 P3953 逛公园【spfa+记忆化dfs+bfs】

    spfa预处理出最短路数组dis,然后反向建边bfs出ok[u]表示u能到n点 然后发现有0环的话时候有inf解的,先dfs找0环判断即可 然后dfs,设状态f[u][v]为到u点,还可以跑最短路+v ...

随机推荐

  1. javaweb笔记—02

    1.compatible:adj. 兼容的:能共处的:可并立的2.web所有的请求都是http请求,http请求默认的编码是ISO-8859-1,不支持utf-8,要统一设置前台和后台一样,才不会乱码 ...

  2. printf("loops %u / %u%c[K\n", loops + 1, opts->loops, 27); printf("%cM", 27);

    serialcheck.c中的一段代码一直弄不明白: do { status = stress_test_uart_once(opts, fd, data, data_len); memset(opt ...

  3. nginx location分析

  4. Centos 7系统虚拟机桥接模式 固定ip

    前言 本文主要给大家介绍了关于Centos 7系统虚拟机桥接模式的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 主机ping不通虚拟机centos7系统的ip大多有以下原 ...

  5. javascript 与 PHP 通信加密,使用AES 128 CBC no padding,以及ios,java,c#文章例子

    运行环境 php7.0 不适用于 php7.0以上版本,因为mcrypt_encrypt()函数已删除 为何要采用 no padding 这种形式: AES加密如果原输入数据不够16字节的整数位,就要 ...

  6. P1357 花园

    洛咕原题 题解 状压dp+矩乘 首先看到题目说M<=5,这么小的数据明显可以用状压保存相邻状态,于是可以得到一个80分的dp: 先筛出所有可用的状态,然后建立一个矩阵保存可转移的状态,再然后把每 ...

  7. neutron full stack

    1.  通读一下 neutron的那个文档.  里面介绍了, db怎么隔离的, amqp怎么隔离的. 2.  记住文档中,那个full stack的图. 3.  走读代码      从TestOvsC ...

  8. update与select关联执行效率问题

    UPDATE fl_user_space u SET u.`course_count` = (SELECT COUNT(*) FROM fl_course c WHERE c.uid = u.uid) ...

  9. linux物理网卡检测命令mii-tool

    mii-tool    #是用于查看.管理物理的网络接口的状态,还可以配置网卡需要的协商方式. 一 ,查看网卡工作状态 mill-tool [网卡名]    #查看物理网卡连接状态 -V 显示版本信息 ...

  10. RedHat7安装Docker

    RedHat 启动 docker报错: 错误:Error starting daemon: SELinux is not supported with the overlay2 graph drive ...