动态规划算法(后附常见动态规划为题及Java代码实现)
一、基本概念
动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
二、基本思想与策略
基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。
与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。
以上都过于理论,还是看看常见的动态规划问题吧!!!
三、常见动态规划问题
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]
代码如下:
- <span style="font-size:18px;">import java.util.*;
- public class Exchange {
- public int countWays(int[] penny, int n, int aim) {
- // write code here
- if(n==0||penny==null||aim<0){
- return 0;
- }
- int[][] pd = new int[n][aim+1];
- for(int i=0;i<n;i++){
- pd[i][0] = 1;
- }
- for(int i=1;penny[0]*i<=aim;i++){
- pd[0][penny[0]*i] = 1;
- }
- for(int i=1;i<n;i++){
- for(int j=0;j<=aim;j++){
- if(j>=penny[i]){
- pd[i][j] = pd[i-1][j]+pd[i][j-penny[i]];
- }else{
- pd[i][j] = pd[i-1][j];
- }
- }
- }
- return pd[n-1][aim];
- }
- }</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]);
代码如下:
- <span style="font-size:18px;">import java.util.*;
- public class MinimumPath {
- public int getMin(int[][] map, int n, int m) {
- // write code here
- int[][] dp = new int[n][m];
- for(int i=0;i<n;i++){
- for(int j=0;j<=i;j++){
- dp[i][0]+=map[j][0];
- }
- }
- for(int i=0;i<m;i++){
- for(int j=0;j<=i;j++){
- dp[0][i]+=map[0][j];
- }
- }
- for(int i=1;i<n;i++){
- for(int j=1;j<m;j++){
- dp[i][j] = min(dp[i][j-1]+map[i][j],dp[i-1][j]+map[i][j]);
- }
- }
- return dp[n-1][m-1];
- }
- public int min(int a,int b){
- if(a>b){
- return b;
- }else{
- return a;
- }
- }
- }</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);
代码如下:
- <span style="font-size:18px;">import java.util.*;
- public class GoUpstairs {
- public int countWays(int n) {
- // write code here
- if(n<=2)
- return n;
- int f = 1%1000000007;
- int s = 2%1000000007;
- int t = 0;
- for(int i=3;i<=n;i++){
- t = (f+s)%1000000007;
- f = s;
- s = t;
- }
- return t;
- }
- }</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]);
代码如下:
- <span style="font-size:18px;">import java.util.*;
- public class LCS {
- public int findLCS(String A, int n, String B, int m) {
- // write code here
- int[][] dp = new int[n][m];
- char[] a = A.toCharArray();
- char[] b = B.toCharArray();
- for(int i=0;i<n;i++){
- if(a[i]==b[0]){
- dp[i][0] = 1;
- for(int j=i+1;j<n;j++){
- dp[j][0] = 1;
- }
- break;
- }
- }
- for(int i=0;i<m;i++){
- if(a[0]==b[i]){
- dp[0][i] = 1;
- for(int j=i+1;j<m;j++){
- dp[0][j] = 1;
- }
- break;
- }
- }
- for(int i=1;i<n;i++){
- for(int j=1;j<m;j++){
- if(a[i]==b[j]){
- dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]);
- }else{
- dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
- }
- }
- }
- return dp[n-1][m-1];
- }
- public int max(int a,int b,int c){
- int max = a;
- if(b>max)
- max=b;
- if(c>max)
- max = c;
- return max;
- }
- }</span>
动态规划算法(后附常见动态规划为题及Java代码实现)的更多相关文章
- JVM组成、GC回收机制、算法、JVM常见启动参数、JAVA出现OOM,如何解决、tomcat优化方法
JVM组成.GC回收机制.算法.JVM常见启动参数.JAVA出现OOM,如何解决.tomcat优化方法
- 排序算法对比,步骤,改进,java代码实现
前言 发现是时候总结一番算法,基本类型的增删改查的性能对比,集合的串并性能的特性,死记太傻了,所以还是写在代码里,NO BB,SHOW ME THE CODE! github地址:https://gi ...
- 多线程动态规划算法求解TSP(Traveling Salesman Problem) 并附C语言实现例程
TSP问题描述: 旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须 ...
- 动态规划算法(Dynamic Programming,简称 DP)
动态规划算法(Dynamic Programming,简称 DP) 浅谈动态规划 动态规划算法(Dynamic Programming,简称 DP)似乎是一种很高深莫测的算法,你会在一些面试或算法书籍 ...
- 动态规划算法详解 Dynamic Programming
博客出处: https://blog.csdn.net/u013309870/article/details/75193592 前言 最近在牛客网上做了几套公司的真题,发现有关动态规划(Dynamic ...
- 算法导论——lec 11 动态规划及应用
和分治法一样,动态规划也是通过组合子问题的解而解决整个问题的.分治法是指将问题划分为一个一个独立的子问题,递归地求解各个子问题然后合并子问题的解而得到原问题的解.与此不同,动态规划适用于子问题不是相互 ...
- 以计算斐波那契数列为例说说动态规划算法(Dynamic Programming Algorithm Overlapping subproblems Optimal substructure Memoization Tabulation)
动态规划(Dynamic Programming)是求解决策过程(decision process)最优化的数学方法.它的名字和动态没有关系,是Richard Bellman为了唬人而取的. 动态规划 ...
- 五大常用算法之二:动态规划算法(DP)
一.基本概念 动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 二.基本思想与策略 基本 ...
- 『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)
本文索引目录: 一.动态规划的基本思想 二.数字三角形.最大子段和(PTA)递归方程 三.一道区间动态规划题点拨升华动态规划思想 四.结对编程情况 一.动态规划的基本思想: 1.1 基本概念: 动态规 ...
随机推荐
- 【Head First Servlets and JSP】笔记12:URL重写
1.会话管理的核心在于“交换会话ID”,来回传递cookie是最简单的方法,容器通过客户端发来的JSSESIONID查找匹配的对话. 2.如果浏览器禁用了cookie,那就意味着浏览器将忽略响应首部中 ...
- Redis之数据存储结构
今天去中关村软件园面试,被问到:你做项目用到的Redis处理数据用的什么结构?顿时石化,”用到的结构,不就是key-value嘛,还有什么结构?“.面试官说:“平时除了工作,要加强学习,下面的面试我觉 ...
- PHP递归和非递归遍历文件夹下文件
function readDirFiles($dir){ $files= []; $queue=[realpath($dir)]; $currentPath = current($queue); wh ...
- CSS3手风琴下拉菜单
在线演示 本地下载
- Springmvc跳转路径
forward转发地址栏不发生变化,redirect跳转地址栏变化,forward能把request域中的参数带给下一个,而redirect不会带过去,但是Springmvc的model虽然是基于re ...
- 使用UNIDAC连接oracle时的参数设置
在uniconnection1里设置: server项位hostip:port:sid,如10.53.x.XX:1521:or10g 然后在Options里设置: charset:utf8 direc ...
- python爬虫-url
特此声明: 以下内容来源于博主:http://blog.csdn.net/pleasecallmewhy http://cuiq ...
- CreateThread创建线程传递结构体参数
#include "stdafx.h" #include <stdio.h> #include <windows.h> #include <stdli ...
- VC读取文件内容
// chopper.cpp : Defines the entry point for the console application. // #include "stdafx.h&quo ...
- Codeforces Round #283 (Div. 2) E. Distributing Parts 贪心+set二分
E. Distributing Parts time limit per test 2 seconds memory limit per test 256 megabytes input standa ...