赞
踩
是求解决策过程(decision process)最优化的数学方法。把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,是一种解决这类过程优化问题的新方法。
动态规划算法通常用于求解具有某种最优性质的问题!!!特别的 ,动态规划(Dynamic Programming)对于子问题重叠的情况特别有效,因为它将子问题的解保存在表格中,当需要某个子问题的解时,直接取值即可,从而避免重复计算!
我们通过一个问题来引出:
提问:动态规划与分治法有什么不同?
说明:具体的填表情况还是要看具体所涉及的情景,有时可能不需要保存全部的子状态,而只需要保存之前的1~2个状态即可。 比如:爬楼梯问题等
适合应用动态规划方法求解的最优化问题应该具备两个重要的要素:最优子结构和子问题重叠。
(a)最优子结构:问题的最优解由相关子问题的最优解组合而成,并且可以独立求解子问题!
(b)子问题重叠:递归过程反复的在求解相同的子问题。
能采用动态规划求解的问题的一般要具有3个性质:
(a) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
(b) 无后效性:即某阶段状态(定义的新子问题)一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与其以前的状态有关。
(c)有重叠子问题:即子问题之间是不独立的(分治法是独立的),一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)
比如下面的问题:相同颜色的子问题就被重复用到。
实际应用中可以按以下几个简化的步骤进行设计:
(1)分析最优解的性质,并刻画其结构特征,这一步的开始时一定要从子问题入手。
(2)定义最优解变量,定义递归最优解公式。
(3)以自底向上计算出最优值(或自顶向下的记忆化方式(即备忘录法))
(4)根据计算最优值时得到的信息,构造问题的最优解
零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount。
编写一个函数来计算可以凑成总金额所需的最少的硬币个数。
如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
用待找零的数值k描述子结构/状态,记作MinCoinCount[k],其值为所需的最小硬币数。对于不同的硬币面值coins[0…n],有 MinCoinCount[k] = min(MinCoinCount[k-coin[0]] , MinCoinCountk-coin[1]], …)+1。对应于给定数目的找零amount,需要求解MinCoinCount[amount]的值。
#include<iostream>
#include<vector>
#include<limits.h>
using namespace std;
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> MinCoinCount(amount+1, INT_MAX-1) ;
MinCoinCount[0] = 0 ;
//MinCoinCount[k],(k为零钱数) MinCoinCount[k] 为所需的最小硬币数量
for (int i = 1 ; i <= amount ; ++i)
{
for (int j = 0; j < coins.size() ; ++j )
{
if ( i - coins[j] >= 0 &&
MinCoinCount[i - coins[j]]+1 < MinCoinCount[i])
MinCoinCount[i] = MinCoinCount[i - coins[j]] + 1 ;
}
}
if (MinCoinCount[amount] == INT_MAX-1 )
return -1 ;
else
return MinCoinCount[amount];
}
};
https://blog.csdn.net/roslei/article/details/60867423
建议没事干的时候把这东西看看:^_^
https://www.sohu.com/a/153858619_466939
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。