动态规划-DynamicProgramming

本文深入探讨动态规划的概念,包括其在计数、最值和存在性问题中的应用。通过一个硬币找零问题,阐述了动态规划的四个基本步骤:确定状态、建立子问题、构建转移方程和设定初始条件与边界条件。同时,指出递归解法的效率问题并提出自底向上的计算顺序以避免重复计算。动态规划是一种强大的算法工具,能解决复杂问题的最优解。
摘要由CSDN通过智能技术生成

1. 动态规划可以解决哪些问题?

(1)计数

-有多少种方式走到右下角

-有多少种方法选出k个数使得和是sum

(2)最值

-从左上角走到右下角路径的最大数字和

-最长上升子序列长度

(3)存在性

-取石子游戏,先手是否必胜

-能不能选出k个数使得和是sum

2. 动态规划步骤

2.1 确定状态 state

状态在动态规划中属于定海神针。简单的说,解动态规划的时候需要开一个数组,数组的每个元素f[i]或者f[i][j]代表什么,类似于数学题中,X, Y, Z代表什么。

确定状态需要两个意识:

1)最后一步

2)子问题

下面以一个例子进行讲解:

有足够多的三种面值的硬币:2元,5元和7元,要支付总额为27元的商品,要求支付的硬币数量最少。

2.1.1 最后一步 

虽然我们不知道最优策略是什么,但最优策略肯定是K枚硬币a1, a2 ... ak面值加起来是27.

所以一定有一枚最后的硬币:ak,除掉这枚硬币,前面的硬币面值加起来是27-ak。

关键点1:

我们不关心前面的k-1枚硬币是怎么拼出27-ak的(可能有1种拼法,也可能有100种拼法),而且我们甚至还不知道ak和k,但我们确定前面的硬币拼出了27-ak。

关键点2:

因为是最优策略,所以拼出27-ak的硬币数一定最少,否则这就不是最优策略了。

2.1.2 子问题

原问题是如何用最少枚硬币拼出27,现在我们将问题转为了:如何用最少枚硬币可以拼出27-ak,转成了一个比原问题规模更小的一个子问题。

为了简化定义,我们设状态f(X)=最少用多少枚硬币拼出X。

但我们还不知道最后那枚硬币ak是多少,但ak只可能是2,5或者7,所以:

1)如果ak是2,则f(27) = f(27-2) + 1(加上最后的这枚2元的硬币);

2)如果ak是5,则f(27) = f(27-5) + 1(加上最后的这枚5元的硬币);

3)如果ak是7,则f(27) = f(27-7) + 1(加上最后的这枚7元的硬币);

除此之外,没有其他可能性了,所以:

f(27) = min(f(27-2) + 1, f(27-5) + 1, f(27-7) + 1)

2.1.3  递归解法

 递归存在的问题:

做了很多重复计算,效率低下。

我们可以将计算的结果保存下来,并改变计算顺序。

2.2 转移方程

设状态f(X)=最少用多少枚硬币拼出X

那么对于任意X,有以下等式:

f(X) = min(f(X-2) + 1, f(X-5) + 1, f(X-7) + 1)

转移方程其实就是将一个大的问题拆分成若干个规模更小的子问题。

2.3 初始条件和边界条件

要解决的是算法的最小拆分单元(再小就不能拆了),以及算法何时结束(不能无止境的计算下去),还要防止程序出现异常(例如数组不能越界),

初始条件f(0) = 0; 状态不能从转移方程求得,但是它是有值的;

2.4 计算顺序

2.4.1 自顶向下

从最大的问题触发开始解,拆分成每个对应的子任务,直到子任务是初始条件。

2.4.2 自底向上

由初始条件f(0) = 0开始,逐步计算f(1), f(2)...f(27)得到结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值