一、基本概念

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

二、基本思想与策略

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

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

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

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

三、常见动态规划问题

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. P4121 [WC2005]双面棋盘

    题目 P4121 [WC2005]双面棋盘 貌似是刘汝佳出的题目?? 做法 线段树维护并查集 线段树分治\(1\)~\(n\)行,我们要考虑维护的肯定是黑.白各自的联通块数量 考虑区间合并,其实就与中 ...

  2. 跨平台移动开发 Xuijs超轻量级的框架 Dom与Event简洁代码实现文本展开收起

    Dom与Event简洁代码实现文本展开收起 Xuijs超轻量级的框架 Dom与Event实现文本展开收起 效果图 示例代码 <!DOCTYPE html PUBLIC "-//W3C/ ...

  3. 主攻ASP.NET MVC4.0之重生:上下滑动屏幕动态加载数据

                @{ ViewBag.Title = "Index"; } <!DOCTYPE html> <html> <head> ...

  4. dll和lib

    lib:里面包含了很多源代码,工程会将这些源代码加入自己的项目中编译: dll:动态编译库,允许可执行文件在运行中加载里面的资源. 使用lib需注意两个文件:(1).h头文件,包含lib中说明输出的类 ...

  5. VCFtools

    The C++ executable module examples This page provides usage examples for the executable module. Exte ...

  6. 主席树----POJ 2104(主席树裸题)(转)

    首先来介绍一下我们需求:给你n个数,多次问你某个区间内的第k小是哪个数 主席树: 主席树的全名应该是 函数式版本的线段树.加上附带的一堆 technology.. ..总之由于原名字太长了,而且 “主 ...

  7. Linux 解压压缩命令

    一.概述: 1.压缩命令: 命令格式:tar  -zcvf   压缩文件名.tar.gz   被压缩文件名 可先切换到当前目录下.压缩文件名和被压缩文件名都可加入路径. 2.解压缩命令: 命令格式:t ...

  8. flsk-SQLALchemy

    SQLALchemy 一.介绍     SQLALchemy是一个基于Python实现的ORM框架.该框架是建立在DB API之上,使用关系对象映射进行数据库操作     简言之便就是:将类和对象转换 ...

  9. openstack Neutron分析(3)—— neutron-dhcp-agent源码分析

    1.neutron dhcp3个主要部件分别为什么?2.dhcp模块包含哪些内容?3.Dnsmasq配置文件是如何创建和更新的?4.DHCP agent的信息存放在neutron数据库的哪个表中? 扩 ...

  10. java中i=i++问题分析

    http://www.ticmy.com/?p=43 重点:局部变量表 和 操作数栈的执行过程. 使用javac编译后再使用javap -c Test反编译这个类查看它的字节码,如下(只摘取main方 ...