什么叫做动态规划
动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
动态规划的思想
动态规划背后的思想很简单,和分治思想类似,将求解的问题分解成若干个子问题,按照顺序求解子问题,列出各种可能的局部解,通过决策(根据题意)保留那些有可能达到最优的局部解,丢弃其它局部解。为了减少重复计算,每个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。但是,和分治算法不同的是,经过分解后得到的子问题往往不是互相独立的,而是下一个子阶段的求解建立在上一个子阶段的解的基础上;
适用场景
最优子结构性质;如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构性质(比如贪心算法就没有)
无后效性;即子问题的解一旦确定,就不再改变,不受在这之后、包含它的更大的问题的求解决策影响
子问题重叠性质;子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的问题并不总是新问题,有些子问题会被计算多次;(动态规划算法正是利用了这种子问题的重叠性质,,因为无后效性,所以对每个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次计算过的子问题的时候,在表格中查找一下结果就行了,从而很大的提升了效率)
具体问题
如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?
假设 d[i] = j 表示凑够 i 元最少需要 j 个硬币,譬如说,当 i 为 0 的时候,需要 0 个硬币(废话),i 为 2 的时候需要 2 个硬币,i 为 3 的时候,出现两个方案,需要做一个选择,是选择 3 个 1 元硬币还是 1 个 3 元硬币,程序要怎么计算出来呢?递归!其实就是 d[3 - 1] (使用 1 元硬币之后,凑够 2 元所需要的最少数量)和 d[3 - 3](使用 3 元硬币之后,0元需要的最少硬币数量),取两者的最小值再加上 1 ;
package com.threetop.www;
/**
* 动态规划解决硬币组合问题
* 有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?
* @author wjgs
*
*/
public class DP {
static int []coin={1,3,5};
public static void dp_fun(int num)
{
//动态规划表存储当前最优解
int[]dp=new int[num+1];
for (int i=1;i<dp.length;i++)
{
int min_val=Integer.MAX_VALUE;
for(int j=0;j<coin.length;j++)
{
//动态规划的核心步骤
if(i>=coin[j])
{
min_val=Math.min(dp[i-coin[j]]+1, min_val);
}
}
dp[i]=min_val;
}
for(int k=0;k<dp.length;k++)
{
System.out.println("凑齐"+k+"元,至少需要"+dp[k]+"枚硬币");
}
}
public static void main(String[] args) {
DP.dp_fun(11);
}
}