C++动态规划(背包问题)

目录

一.动态规划是什么

二.动态规划的运用

(1).用动态规划解决重复子问题

(2).动态规划使用的条件与流程

Ⅰ.动态规划的使用条件:

Ⅱ.动态规划的使用流程

(3).背包问题

三.背包问题:

(1).0/1背包

Ⅰ.朴素方法:

Ⅱ.滚动数组优化 :

Ⅲ.一维数组:

(2).多重背包

(3).完全背包

(4).混合背包

(5).分组背包

(6).二维费用背包


一.动态规划是什么

计算机相对于人类来说的优势有三点,一点是他的运行速度,第二点是准确性,第三点则是处理问题的时候逻辑十分清晰。所以我们一般在编程时用的有两种方法,一是运用计算机的快速计算能力进行暴力枚举法、另一个则是将一个大问题分成小问题,求出所有小问题的答案再组合在一起得出正确答案的分解问题法。其中分解问题法需要能熟悉的掌握分解题目的方式以及能够熟练的运用递归,分治和贪心等算法。但他们各有他们的劣势。就比如贪心算法,在三角形中寻找最短的边的时候,他会在每一个节点是选择边较长的那一个。但是他不会考虑到较短的那条边连接的下一条边是否更长,所以贪心算法虽然时间复杂度较低,但他得出来的是较优解,而不是最优解。

举个例子:

货币面额有1,2,5,10,20,50,100,每种数量都无限多,现在给出金额n(1<=n<=1e6),求出构造金额n的最少货币数量

贪心策略:分成若干次选择,每一次选择比n小且最接近n的货币。

但是如果当n=7是,货币金额分别为3、1、4、5时,如果先选择5的话就没法凑出7。

如果我们将构造某个金额所需要的最少货币数量作为一个问题,并且用数组储存答案。那么在求解某个原问题的时候,我们只需要考虑原问题由哪一个子问题推出能得到更优解即可。

如本题:我们用f[i]表示金额为i的最少需要的硬币的总数量。

明显可以发现:f[1]=1 / f[2]=2 / f[3]=2 / f[4]=2 / f[5]=1 / f[6]=3 ......

而f[7]有多种组成,比如:

f[7]=f[6]+f[1]=f[5]+f[2]=f[4]+f[3]=f[5]+f[1]+f[1]......,我们从中选择一个解使得f[7]最小即可。像这样我们把每个子问题的解储存下来,最终可以知道原问题的解一定可以由子问题推出。将求解变成一个递推,与普通递推不一样的地方在于原问题可能会由多个子问题推出,我们选最优的即可。

这就是动态规划(DP)的基本思想,以空间换时间,存放各子问题的解以便能推出原问题。这样可以充分保证求解的正确性。具体讲解放在下一部分。

二.动态规划的运用

(1).用动态规划解决重复子问题

动态规划其实和分治算法的想法相同,保证可以通过子问题来推出原问题的最终答案,而且在处理重复子问题的时候非常的高效。我们在进行搜索剪枝的时候,对于无法避免的较多重复的子问题,我们通常采用记忆化的方式进行处理。但由于其使用了递归的方法,对于规模比较大的问题,他依旧会超时。但如果使用动态规划的话,因为其本质为递推,所以对于重复子问题可以进行高效的处理。另外我们还知道,子问题越多那么复杂度越高,如果我们将子问题的规模缩小(多个有相同性质的子问题合并视作一个),那么复杂度将会大大减小。

像上一道题一样,我们将所有金额为7的组合视作一个集合。集合的值为最少货币数量显然,集合的允许加入条件越宽松,那么重复子问题就越多,要处理的节点也就越少。

(2).动态规划使用的条件与流程

Ⅰ.动态规划的使用条件:

1.重复子问题:存在大量子问题进行了重复计算。

2.具备最优子结构:后面阶段的状态可以通过前面子问题状态推导出来。

3.无后效性:已经求解的子问题,不会再受到后续决策的影响。即从关系图上而言是一个DAG。

Ⅱ.动态规划的使用流程

1.划分子问题。即定义集合,描述状态。

2.确定状态转移方程。即子问题的解如何推出原问题

3.确定初始值

4.确定遍历顺序,保证求某问题时,其涉及到的子问题的解已经全部求出。即从小到大填出dp表

(3).背包问题

背包问题‌是一个经典的动态规划问题,它描述了一个旅行者有一个最多能装m公斤的背包,现在有n件物品,每件物品有各自的重量和价值。他的要求是选择装入背包的物品,使得背包内物品的总价值最大,同时不超过背包的容量限制。这个问题通常被称为0/1背包问题,因为每个物品只有两种选择:装入背包或不装入背包。

背包问题与动态规划算法是密不可分的,该算法通过构建一个表格来记录每个子问题的解,最终找到最优解。具体来说,对于每个物品i

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值