1月2日上课笔记

文章介绍了如何使用动态规划解决最少硬币组合问题,通过状态转移方程展示递推过程,并提供了C++代码实现。接着,讨论了01背包问题,解释了问题定义、目标函数和约束条件,并展示了计算最优解的动态规划算法及对应代码示例。
摘要由CSDN通过智能技术生成

一、硬币问题:

最少硬币问题

  有n种硬币,面值分别为v1,v2,v3···,vn,数量无限。输入非负整数s。要求输出最少的硬币组合。

  定义一个数组int Min[],其中MIn[i]是金额i对应的最少硬币数量。

  以五种面值(1、5、10、25、50)的硬币为例演示递推过程。

  1. 只使用最小面值的1分硬币:Min[0]=0 -> Min[1] = Min[1-1] + 1 = 1 -> Min[2] = Min[2-1] + 1 = 2,持续这个过程,得到递推关系MIn[i] = min(Min[i], Min[i-1] + 1) 。

  2. 在使用1分硬币的基础上增加使用第二小面值5分硬币:Min[5] = Min[5-5] + 1 =1 -> Min[6] = Min[6-1] + 1 = 6。持续这个过程,得到递推关系Min[i] = min(Min[i], MIn[i-5] + 1)。

  继续处理其他面值的硬币,从Min[i-1]或Min[i-5]得到Min[i]的递推关系成为 “状态转移” 。而根据之前递推的规律,我们可以总结得出Min[i] = min(Min[i], Min[i-x] + 1(x为硬币的面值)。

代码如下:

打印最少硬币的组合

  这种题目状态表需要适当的扩展,以包含更多信息。可以通过增加一个记录表Min_path[i]来记录金额i需要的最后一个硬币。利用记录表逐步倒推来获得所有的硬币。

所有硬币组合

问题:有5中面值的硬币,即1分、5分、10分、25分、50分。输入一个钱数s,输出组合方案的数量。例如11分有四种组合方案,即11个1分、2个5分+1个1分、1个5分+6个1分、1个10分+1个1分。s≤250,硬币数量num≤100。

不完全解决方案

  假设硬币数量不限,模仿前面最少硬币问题的状态转移也能容易地递推出这题的状态转移:dp[i] = dp[i] + dp[i-x](x为硬币面值)。

代码如下:

完全解决方案

  定义一个二维数组int dp[][]其中dp[i][j]的含义是用j个硬币实现金额i的方案数量。递推得到状态转移:dp[i][j] = dp[i][j] + dp[i-x][j-1]。

代码如下:

二、01背包问题:

1.问题描述

给定一个物品集合s={1,2,3,…,n},物品i的重量是wi,其价值是vi,背包的容量为W,即最大载重量不超过W。在限定的总重量W内,我们如何选择物品,才能使得物品的总价值最大。

如果物品不能被分割,即物品i要么整个地选取,要么不选取; 不能将物品i装入背包多次,也不能只装入部分物品i,则该问题称为0—1背包问题,适合使用DP。

如果物品可以拆分,则问题称为背包问题,适合使用贪心算法。

2.分析问题

假设xi表示物品i装入背包的情况

当xi=0时,表示物品没有装入背包;

当xi=1时,表示把物品装入背包。

约束方程: ≤W

目标函数:

因此问题就归结为找到一个满足上述约束方程, 并使目标函数达到最大的解向量: X={x1,x2,…,xn}

0-1背包问题的子问题: i≤k≤n的最优值为p(i,j)

p(i,j)是背包容量为j,可选物品为i,i+1,…,n时0-1背包问题的最优值!

此时一定要理解公式p(i,j)的意思。

3.过程推理

W=5

1

2

3

4

重量w

2

1

3

2

价值v

12

10

20

15

p[2][1]=max(p[3][1],p[3][0]+10)=10;

p[2][2]=max(p[3][2],p[3][1]+10)=15;

p[2][3]=max(p[3][3],p[3][2]+10)=25;

p[2][4]=max(p[3][4],p[3][3]+10)=30;

p[2][5]=max(p[3][5],p[3][4]+10)=35;

p[1][5]=max(p[2][5],p[2][3]+12)=37;

从下向上,从左到右填表

第4行,只考虑物品4,物品4的重量是2,价值是15

背包容量为0和1的时候,放不进去4,因此p[4][0]=p[4][1]=0

背包容量为2,3,4,5的时候,放进一个4,因此p[4][2]=p[4][3]=p[4][4]=p[4][5]=15

第3行,只考虑物品4和3,物品4的重量2,价值15;物品3的重量3,价值20

以p[3][5]为例,代入上述方程可得:

p[3][5]=max(p[4][5],p[4][5-3]+20)=35

5-3的3是物品3的重量,20是物品3的价值

意思是j(5)>wi(3),此时物品3可以放进背包

如果物品3性价比不高,就选择不放进来,p[3][5]=p[4][5]

如果物品3性价比高,就选择放进背包,p[3][5]=p[4][2]+20,意思是物品3放入背包,背包容量变为2,而价值增加20

p[3][5]=p[4][5]=15

意思是如果j<wi,此时物品i不能放进背包

我们最终需要的结果放在了p[1][5]中

求p[1][5]需要用到第二行的数据,而p[1][0~4]的数据都没有用,可以置0

p[1][5]=max(p[2][5],p[2][5-3]+20)=35

p[1][5]=p[4][5]=15

代码如下:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值