如何解决Python在约束下找到最大值 代码:说明:
我正在自己学习 Python,但无法为特定问题找到正确的解决方案:
我得到 x $。 我可以购买一系列不同的物品,每个物品都有特定的价格(成本)并提供特定的收益(收益) 我想获得 x $ 的最大增益。 每个项目只有 1 个。 让我们说:
dollars = 10
cost = [5,4,1,10]
gain = [7,6,12]
此处 => 最大增益为 17
使用基于排列的幼稚解决方案,当项目数量较少时,我设法找到了解决方案。 但是当item数量增加时,时间增加,电脑死机。
有没有一种典型的算法可以解决这种 pb 问题?
解决方法
您在其中一条评论中提到对解决方案的代码不感兴趣,所以我只会解释算法。这个问题被称为0-1 knapsack problem。 解决它的典型方法是使用 dynamic programming:
- 让我们定义一个我们称之为
m(i,c)
的值,它是您最多花费c
$ 并且只购买前i
列表。 你有: -
m(0,c) = 0
(如果你买不到任何东西,你就不会得到任何收益)。 -
m(i,c) = m(i-1,c)
ifcost[i]>c
(如果新商品超过成本限制,您无论如何都无法购买) -
m(i,c) = max(m(i-1,c),m(i-1,c-cost[i]) + gain[i])
ifcost[i]<=c
(您现在可以购买商品i
。要么购买,要么不购买,以及从中获得的最大收益它是这两个选项中的最大值)
要获得最优惠的价格,您只需计算 m(len(cost),dollars)
。例如,您可以使用 for
循环来执行此操作,通过填充 m(i,dollars)
值列表,您将为每个 i
计算 len(cost)
,直到 m
.要确定实际购买了哪些商品,而不仅仅是最大收益,您必须在填写 m
时将它们保存在单独的列表中。
这听起来像是一个 LeetCode 问题,但我会给你一个体面的答案(不是最好的,绝对可以优化):
问题
假设您试图从串在一起的任何 n 个项目中找到最大增益量而不重复任何项目,则以下算法可以工作。
解决方案
您将采用压缩成本和收益的最高比率,并从压缩变量中删除该索引。然后,您将重做该问题,直到您没有足够的钱购买任何商品:
代码:
#!/usr/bin/env python3
dollars = 10
cost = [5,4,1,10]
gain = [7,6,12]
result_gain = 0
zipped = [i for i in zip(cost,gain)]
largestgain = []
# create ratio of cost to gain and pick from the smallest to the largest
ratios = []
for x in zipped:
# divide the gain by the cost
ratios.append(x[1]/x[0])
# create a largest variable to grab the largest ratio from a for loop for every updated index
largest = 0
for x in range(0,len(zipped)):
for index,ratio in enumerate(ratios):
if index == 0:
largest = ratio
else:
if ratio > largest:
largest = ratio # let largest be the new largest ratio
# get the index of the largest ratio
largest = ratios.index(largest)
print(largest)
# append the largest gain to a list of what should be added up later
largestgain.append(zipped[largest])
# check if dollars,when subtracted from the first index,yield less than 0
if dollars - zipped[largest][0] < 0:
break
# if not,subtract dollars from total and update resulted gain
else:
dollars = dollars - zipped[largest][0]
result_gain = result_gain + zipped[largest][1]
# delete the largest zipped variable in order to redo this process
del zipped[largest]
# delete the largest ratio as well in order to redo this process
del ratios[largest]
# print the list that would yield you the largest ratios in order from largest to smallest,but in the form of a zipped list
print(largestgain)
# The max amount of gain earned
print(result_gain)
说明:
我添加了shebang,以便您可以自己测试它,但它应该可以完美运行。我已经注释了我的代码,以便您可以阅读算法的过程。如果您愿意,可以使用更大的列表进行测试。
请注意,成本列表和增益列表的长度没有异常检查器,因此如果成本列表大于增益列表,它将划分一个不存在的缓冲区并抛出异常。
如果此算法太慢,请随时查看此 resource 以获取其他背包算法解决方案。这个很优雅,但其他的就不那么优雅了。
编辑:
正如评论者所指出的,这是一种非常贪婪的算法,并不适用于所有值。请参阅理论以获得更好的解释。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。