微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python在约束下找到最大值 代码:说明:

如何解决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) if cost[i]>c(如果新商品超过成本限制,您无论如何都无法购买)
  • m(i,c) = max(m(i-1,c),m(i-1,c-cost[i]) + gain[i]) if cost[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 举报,一经查实,本站将立刻删除。