一、基本概念

动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。

二、基本思想与策略

基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。

与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。

以上都过于理论,还是看看常见的动态规划问题吧!!!

三、常见动态规划问题

1、找零钱问题

有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。
给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。
测试样例:
[1,2,4],3,3
返回:2

解析:设dp[n][m]为使用前n中货币凑成的m的种数,那么就会有两种情况:

使用第n种货币:dp[n-1][m]+dp[n-1][m-peney[n]]

不用第n种货币:dp[n-1][m],为什么不使用第n种货币呢,因为penney[n]>m。

这样就可以求出当m>=penney[n]时 dp[n][m] = dp[n-1][m]+dp[n-1][m-peney[n]],否则,dp[n][m] = dp[n-1][m]

代码如下:

  1. <span style="font-size:18px;">import java.util.*;
  2. public class Exchange {
  3. public int countWays(int[] penny, int n, int aim) {
  4. // write code here
  5. if(n==0||penny==null||aim<0){
  6. return 0;
  7. }
  8. int[][] pd = new int[n][aim+1];
  9. for(int i=0;i<n;i++){
  10. pd[i][0] = 1;
  11. }
  12. for(int i=1;penny[0]*i<=aim;i++){
  13. pd[0][penny[0]*i] = 1;
  14. }
  15. for(int i=1;i<n;i++){
  16. for(int j=0;j<=aim;j++){
  17. if(j>=penny[i]){
  18. pd[i][j] = pd[i-1][j]+pd[i][j-penny[i]];
  19. }else{
  20. pd[i][j] = pd[i-1][j];
  21. }
  22. }
  23. }
  24. return pd[n-1][aim];
  25. }
  26. }</span>

2、走方格问题

有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。
给定一个矩阵map及它的行数n和列数m,请返回最小路径和。保证行列数均小于等于100.
测试样例:
[[1,2,3],[1,1,1]],2,3
返回:4

解析:设dp[n][m]为走到n*m位置的路径长度,那么显而易见dp[n][m] = min(dp[n-1][m],dp[n][m-1]);

代码如下:

  1. <span style="font-size:18px;">import java.util.*;
  2. public class MinimumPath {
  3. public int getMin(int[][] map, int n, int m) {
  4. // write code here
  5. int[][] dp = new int[n][m];
  6. for(int i=0;i<n;i++){
  7. for(int j=0;j<=i;j++){
  8. dp[i][0]+=map[j][0];
  9. }
  10. }
  11. for(int i=0;i<m;i++){
  12. for(int j=0;j<=i;j++){
  13. dp[0][i]+=map[0][j];
  14. }
  15. }
  16. for(int i=1;i<n;i++){
  17. for(int j=1;j<m;j++){
  18. dp[i][j] = min(dp[i][j-1]+map[i][j],dp[i-1][j]+map[i][j]);
  19. }
  20. }
  21. return dp[n-1][m-1];
  22. }
  23. public int min(int a,int b){
  24. if(a>b){
  25. return b;
  26. }else{
  27. return a;
  28. }
  29. }
  30. }</span>

3、走台阶问题

有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法。为了防止溢出,请将结果Mod 1000000007
给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。
测试样例:
1
返回:1

解析:这是一个非常经典的为题,设f(n)为上n级台阶的方法,要上到n级台阶的最后一步有两种方式:从n-1级台阶走一步;从n-1级台阶走两步,于是就有了这个公式f(n) = f(n-1)+f(n-2);

代码如下:

  1. <span style="font-size:18px;">import java.util.*;
  2. public class GoUpstairs {
  3. public int countWays(int n) {
  4. // write code here
  5. if(n<=2)
  6. return n;
  7. int f = 1%1000000007;
  8. int s = 2%1000000007;
  9. int t = 0;
  10. for(int i=3;i<=n;i++){
  11. t = (f+s)%1000000007;
  12. f = s;
  13. s = t;
  14. }
  15. return t;
  16. }
  17. }</span>

4、最长公共序列数

给定两个字符串A和B,返回两个字符串的最长公共子序列的长度。例如,A="1A2C3D4B56”,B="B1D23CA45B6A”,”123456"或者"12C4B6"都是最长公共子序列。
给定两个字符串A和B,同时给定两个串的长度n和m,请返回最长公共子序列的长度。保证两串长度均小于等于300。
测试样例:
"1A2C3D4B56",10,"B1D23CA45B6A",12
返回:6

解析:设dp[n][m] ,为A的前n个字符与B的前m个字符的公共序列长度,则当A[n]==B[m]的时候,dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]),否则,dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);

代码如下:

    1. <span style="font-size:18px;">import java.util.*;
    2. public class LCS {
    3. public int findLCS(String A, int n, String B, int m) {
    4. // write code here
    5. int[][] dp = new int[n][m];
    6. char[] a = A.toCharArray();
    7. char[] b = B.toCharArray();
    8. for(int i=0;i<n;i++){
    9. if(a[i]==b[0]){
    10. dp[i][0] = 1;
    11. for(int j=i+1;j<n;j++){
    12. dp[j][0] = 1;
    13. }
    14. break;
    15. }
    16. }
    17. for(int i=0;i<m;i++){
    18. if(a[0]==b[i]){
    19. dp[0][i] = 1;
    20. for(int j=i+1;j<m;j++){
    21. dp[0][j] = 1;
    22. }
    23. break;
    24. }
    25. }
    26. for(int i=1;i<n;i++){
    27. for(int j=1;j<m;j++){
    28. if(a[i]==b[j]){
    29. dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]);
    30. }else{
    31. dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
    32. }
    33. }
    34. }
    35. return dp[n-1][m-1];
    36. }
    37. public int max(int a,int b,int c){
    38. int max = a;
    39. if(b>max)
    40. max=b;
    41. if(c>max)
    42. max = c;
    43. return max;
    44. }
    45. }</span>

动态规划算法(后附常见动态规划为题及Java代码实现)的更多相关文章

  1. JVM组成、GC回收机制、算法、JVM常见启动参数、JAVA出现OOM,如何解决、tomcat优化方法

    JVM组成.GC回收机制.算法.JVM常见启动参数.JAVA出现OOM,如何解决.tomcat优化方法

  2. 排序算法对比,步骤,改进,java代码实现

    前言 发现是时候总结一番算法,基本类型的增删改查的性能对比,集合的串并性能的特性,死记太傻了,所以还是写在代码里,NO BB,SHOW ME THE CODE! github地址:https://gi ...

  3. 多线程动态规划算法求解TSP(Traveling Salesman Problem) 并附C语言实现例程

    TSP问题描述: 旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须 ...

  4. 动态规划算法(Dynamic Programming,简称 DP)

    动态规划算法(Dynamic Programming,简称 DP) 浅谈动态规划 动态规划算法(Dynamic Programming,简称 DP)似乎是一种很高深莫测的算法,你会在一些面试或算法书籍 ...

  5. 动态规划算法详解 Dynamic Programming

    博客出处: https://blog.csdn.net/u013309870/article/details/75193592 前言 最近在牛客网上做了几套公司的真题,发现有关动态规划(Dynamic ...

  6. 算法导论——lec 11 动态规划及应用

    和分治法一样,动态规划也是通过组合子问题的解而解决整个问题的.分治法是指将问题划分为一个一个独立的子问题,递归地求解各个子问题然后合并子问题的解而得到原问题的解.与此不同,动态规划适用于子问题不是相互 ...

  7. 以计算斐波那契数列为例说说动态规划算法(Dynamic Programming Algorithm Overlapping subproblems Optimal substructure Memoization Tabulation)

    动态规划(Dynamic Programming)是求解决策过程(decision process)最优化的数学方法.它的名字和动态没有关系,是Richard Bellman为了唬人而取的. 动态规划 ...

  8. 五大常用算法之二:动态规划算法(DP)

    一.基本概念 动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 二.基本思想与策略 基本 ...

  9. 『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)

    本文索引目录: 一.动态规划的基本思想 二.数字三角形.最大子段和(PTA)递归方程 三.一道区间动态规划题点拨升华动态规划思想 四.结对编程情况 一.动态规划的基本思想: 1.1 基本概念: 动态规 ...

随机推荐

  1. [APIO2013]机器人

    题目描述 VRI(Voltron 机器人学会)的工程师建造了 n 个机器人.任意两个兼容的机 器人站在同一个格子时可以合并为一个复合机器人. 我们把机器人用 1 至 n 编号(n ≤ 9).如果两个机 ...

  2. Listening Carefully SP1403S

    Listening Carefully仔细聆听When people talk, listen completely. Most people never listen. ―Ernest Heming ...

  3. 主攻ASP.NET MVC4.0之重生:Jquery Mobile 按钮+对话框使用

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. mongodb $where 查询中的坑

    mongodb 查询中坑就是数字开头的字段不能用点号,只能用[""].例如: 即:db.datas.find({$where:"this['54bcfc6c329af61 ...

  5. 吴恩达深度学习笔记(八) —— ResNets残差网络

    (很好的博客:残差网络ResNet笔记) 主要内容: 一.深层神经网络的优点和缺陷 二.残差网络的引入 三.残差网络的可行性 四.identity block 和 convolutional bloc ...

  6. Kubernetes TLS认证

    转自: https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/ 前段时间撸了一会 Kubernetes 官方文档,在查看 TLS ...

  7. Servlet和Filter的url匹配以及url-pattern详解

    Servlet和filter是J2EE开发中常用的技术,使用方便,配置简单,老少皆宜.估计大多数朋友都是直接配置用,也没有关心过具体的细节,今天遇到一个问题,上网查了servlet的规范才发现,ser ...

  8. 逆向破解学习二之<TraceMe>

    这次在破解TraceMe的时候,我有看过别人的视频.但是我并没有按照别人思路走,而是完全安全自己的思路试了一次.结果破解成功.新手学破解,如果有不对的地方,还请指出来. 004013A0 crackm ...

  9. JavaWeb -- JSP+JavaBean模式

    SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式,一种是Servlet+JSP+JavaBean模式. JSP+JavaBean模式适合开发业务 ...

  10. 【转】移动oracle LOB索引到其他表空间

    http://blog.chinaunix.net/uid-22948773-id-3451103.html