【动态规划】从子集和问题到背包问题

本文探讨了如何使用动态规划解决子集和问题,即在不超过界限W的情况下,从具有权值的元素集合中选取部分元素,使权值之和最大化。通过实例解释了解题思路,给出了算法伪代码及C++代码实现。接着,文章将问题拓展至背包问题,即在权值和价值双约束下,寻找最大价值的元素组合。动态规划方法同样适用,但需将权值替换为价值进行计算。
摘要由CSDN通过智能技术生成

一、问题定义

有一个包含n个元素{e1, e2, …, en}的集合S,每个元素ei都有一个对应的权值wi。现在有一个界限W,我们希望从S中选择出部分元素,使得这些元素的权值之和在不超过W的情况下达到最大,这个便是子集合问题(事实上还有其他类型的子集和问题,本文暂不讨论)。举个更具体一点的例子,某农民今年收成小番茄总重量为W万斤,有n个采购商想要向这位农民收购小番茄,他们想要采购的数目都有所不同,采购商i想要收购wi万斤小番茄(1 <= i <= n)。现在农民需要从采购商中挑选部分买家,将小番茄卖给他们,使得自己被收购的小番茄数目达到最大,从而赚取最大的收入(假设所有采购商给出的单位收购价都是一样的;所有采购商的收购量总和超过农民的收成量,即农民无法满足所有采购商;收购商i想要收购wi万斤小番茄,他不会只收购一半或者更多)。

二、解决思路

根据动态规划的思路,我们来分析一下这个问题的子问题。假设农民已经从前面n-1个收购商中选出了一组最优组合使得收购量最大,现在他要考虑是否要卖给最后一个收购商n。假如卖给收购商n,那么他能够卖给前面n-1个收购商的番茄就只有(W-wn)万斤。如果他不卖给收购商n,那么他能够卖给前面n-1个收购商的番茄就是W万斤了。于是,假设在只有(W-wn)万斤的情况下,从前面n-1个收购商中选出最优组合所收购的总重量加上卖给收购商n的重量为(O1+wn)。若W万斤都卖给前面n-1个收购商,他们之中选出的最优组合所收购的总重量为O2。农民需要考虑的问题就变成了比较(O1+wn)和O2的大小了。

我们更形式化一点地进行描述,假设O(i, w)表示将w万斤小番茄提供给收购商{1, 2, …, i}收购的时候,从这i个收购商中选出最优组合所收购的总重量。那么O1 = O(n-1, W-wn),O2 = (n-1, W)。当农民考虑收购商n的时候,他需要判定O1和O2的大小。另外一种特殊情况,当收购商收购的数量wn超过农民拥有的所有小番茄的时候,即W < wn,那么农民自然只能考虑前面n-1个收购商中的最优组合了。

更进一步考虑,当我们考虑O(i, w)的时候,如果w能够容纳wi,那么我们需要考虑O(i-1, w)和(O(i-1, w-wi) + wi)的大小。如果w无法容纳wi,即w < wi,那么无需考虑i,O(i, w) = O(i-1, w)。因此,我们可以得到递推公式如下所示:

if w < wi, O(i, w) = O(i-1, w)
else O(i, w) = max(O(i-1, w), wi + O(i-1, w-wi))

得到了递推公式,我们自然就可以得到一个算法来算出最优解。算法的伪代码如下所示:

数组O[0...n, 0...W]
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值