什么是动态规划算法?
动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果。
基本思想
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。
动态规划算法介绍
1)动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法
2)动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
3)与分治法不同的是,适合于用动态规划求解的问题,经分解得到的子问题往往不是互相独立的。(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,
进行进一步的求解)
4)动态规划可以通过填表的方式来逐步推进,得到最优解。
下面举个例子:
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins = [2], amount = 3
输出:-1
示例 3:
输入:coins = [1], amount = 0
输出:0
代码示例:
package com.common.utils;
/**
* @ClassName CoinChange
* @Description: 动态规划算法,用java解决零钱兑换问题
* 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
* 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
* 你可以认为每种硬币的数量是无限的。
* @Author: mischen
* @date: 19:57 2022/12/1
* @Version 1.0
*/
public class CoinChange {
public static void main(String[] args) {
int[] coins = {1,2,5};
int M = 11;
int i = coinChage(coins, M);
System.out.println(i);
int[] coins1 = {2};
int t = coinChage(coins1, 3);
System.out.println(t);
}
/**
*
* @param coins 代表硬币的种类
* @param M 代表拼凑的值 11
* @return
*/
public static int coinChage(int[] coins, int M) {
int[] f = new int[M + 1];
//number of kinds of coins
int n = coins.length;
//initialization
f[0] = 0;
for (int i = 1; i <= M; i++ ){
f[i] = Integer.MAX_VALUE;
//f[X]=min{f[X-2]+1,f[X-5]+1,f[X-7]+1}
for (int j = 0; j < n; j++) {
if (i >= coins[j] && f[i-coins[j]] != Integer.MAX_VALUE) {
f[i] = Math.min(f[i-coins[j]] + 1, f[i]);
}
}
}
if (f[M] == Integer.MAX_VALUE) {
return -1;
}
return f[M];
}
}