背包问题
这个背包问题(也称为“背包问题”)是计算机科学中一个广为人知的组合优化问题。在这个wiki中,您将学习如何使用动态规划来解决背包问题。
介绍
背包的问题可以表述如下:
给定一组不同的物品,每个物品都有相应的价值和重量,决定你应该挑选哪些物品,以便在不超过背包容量的情况下最大化这些物品的价值。
具体地说,假设我们有以下一组有价值的物品和一个给定的背包。
假设你有一组5个项目:
第一项 第二项 第三项 第四项 第五项 值: $5 $10 $3 $2 $3 重量: 4公斤 8公斤 3公斤 5公斤 2公斤 如果你背包的重量限制是 什么是最佳解决方案?也就是说,你应该随身携带哪些物品?
在这种情况下,解决方案是明确的。一个会取第二项和最后一项,得到值为 在完全满足权重限制的情况下,我们在不违反问题约束的情况下实现了最大可能值。
然而,评估所有的可能性通常是非常不实际的,所以我们想知道是否有更好的方法来处理这个问题。事实上,是有的,我们将在下一节中看到一个算法。
伪代码
这个问题可以用简单的递归和一个二维数组来解决。
首先,我们应该为我们的问题找到一个方便的表示,并仔细定义它 物品,每个物品都有价值 和重量 ,我们的包总重量限制为 .
现在我们构造一个 表:
表中的每个单元格都有值 ,在那里 代表了 争吵 代表了 列。
我们能得到的最大值是使用第一个集合的任意组合吗 不超过一定重量的列表项目 。这样,我们就可以为表识别递归:
背包问题的递归:
让我们试着解释这个递归:
假设你有一个确定的值 在您的表中,这意味着使用第一个变量的任意组合可以获得的最大值 列表中的项目和每个项目的重量总和不超过 .如果我们能做到这一点,很明显我们可以用第一个 我们找到了递归的第一种情况,非常简单:
递归的第二种情况是怎样的呢?
鉴于 可以说, 因为如果我们能得到一个确定的值 使用第一个 项目的列表,我们也可以添加 物品清单上的背包,它将不会超过目前的限制 因为在我们得到 项,当前权重为 ,因此,如果我们添加 项的当前权重将变为 ,因此我们保持当前权重等于权重限制,新值将为 加上该项的值 然后 就变成了 .然而,这并不总是最好的选择。如果 Is bigger,我们将使用这个值来代替 回想起 只计算最大值,因此我们将始终选择最佳选项。
最后是max ()
函数评估最佳选项(即找到最大值)。
为了找到最大可能的价值,我们只需要 i、 e.使用 我们清单上的项目,而总重量小于容量 我们的袋子
背包问题的复杂性
在这个问题中,我们采用了高度矩阵 和宽度 ,我们的算法遍历每个单元格一次 因此,背包问题的复杂性是
12 3 4 5 6 7 8 9 10 11 12 13 14 |
|
现在我们将解决第一个示例:
您将获得一组五个项目 每个都在括号内有相应的值和权重
知道背包的重量限制后,你能得到的最大可能值是多少
让我们开始填满我们的表格:
我们知道第一行的所有单元格都是零,因此下表:
通过递归,我们知道 .但是,当 我们有 .这是因为在这一点上 物品的重量是 和 ,因此它满足递归的第二种情况的条件。我们知道
这
因此,这里的最大值是 ,然后 .我也这么做 到 我们还将获得 因此,我们的表格如下所示:
现在 我们将继续做同样的过程。通过计算,我们会看到 从 到 和 从 到 当 我们有 所以我们要分析这两种情况:
和
第二个选择是最好的,所以
做同样的事情,直到我们完成这一行,我们得到
继续用递归来填满第三和第四行,直到最后一行:
当你到达 你会看到
和
最后一个单元格
和
因此 .
这是我们的完整表格:
我们能得到的最大值是 ,可以使用第二项和最后一项来实现。通过这样做,总重量将是 (等于容量,即10),总值为
以下是可以用来解决此问题的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67#包括< iostream >#包括因为<字符串>/*背包问题*///W=背包容量/ / w[我]= i物品的重量/ / v[我]= i项的值//比较两个值并返回较大的那个int最大限度(intA.,intB){如果(A.>=B)返回A.;其他的返回B;}使用名称空间性病;int主要(){intW,v[One hundred.],W[One hundred.];int我,J,N;int表格[One hundred.][10000];//读取W和项数ncin>>W>>N;//读取每一项的权重和值对于(我=1.;我<=N;我++){cin>>W[我]>>v[我];}//使第一行中的每个单元格都等于零对于(J=0;J<=W;J++)表格[0][J]=0;//满桌对于(我=1.;我<=N;我++)对于(J=0;J<=W;J++){//递归的第一种情况如果(W[我]>J)表格[我][J]=表格[我-1.][J];//第二种情况其他的表格[我][J]=最大限度(表格[我-1.][J],表格[我-1.][J-W[我]]+v[我]);}库特<<"\ n";//显示表格对于(我=0;我<=N;我++){库特<<"\ n";对于(J=0;J<=W;J++){库特<<表格[我][J]<<”“;}}//打印答案库特<<"\ n最大值:\ n";库特<<表格[N][W];库特<<"\n\n";返回0;}
应用
虽然简单地陈述和解决了背包问题,但如果不将背包问题用作许多实际问题的原型,背包问题可以直接映射。直接应用包括:
- 一家运输公司试图在不破坏运输飞机重量的前提下,把同样多的包裹装进运输飞机,
- 专业运动队希望组建一支满足各种统计预测且不打破工资上限的队伍,以及
- Soylent需要满足每日的营养需求,同时保持每次食用一定量的粉末。
更有趣的应用包括:
- 对冲基金需要投资以使潜在收益最大化,同时将风险价值(VaR)保持在给定的阈值以下。
- 划分选区的政治区域的形成。每个城镇都有人口 ,和一个分数 投票给该党的人口中 .控制选区选择的政治团体(政党甲)要以数量作选区 尽可能多,同时保持总人数低于一定的限制,并保持一组连续的城镇。
约束优化是管理各种操作中最常见的难题之一。考虑到其设置的简单性、可用于解决的技术的多样性以及它对实际问题的直接应用,背包问题是一个优秀的玩具模型,可以作为优化中更高级问题的丰富训练场地性。