python - 从较小的包裹中完成订单?

标签 python

输入是一个整数,指定要订购的数量。 必须使用预定义的包装尺寸来创建该订单。

例如

Packs
3 for $5
5 for $9
9 for $16

对于输入订单 13,输出应为:

2x5 + 1x3

到目前为止,我有以下方法:

remaining_order = 13
package_numbers = [9,5,3]
required_packages = []

while remaining_order > 0:
    found = False
    for pack_num in package_numbers:
        if pack_num <= remaining_order:
            required_packages.append(pack_num)
            remaining_order -= pack_num
            found = True
            break

    if not found:
        break

但这会导致错误的结果:

1x9 + 1x3 剩余:1

最佳答案

那么,您需要用包裹填写订单以使总价最高吗?这被称为 Knapsack problem .在那篇维基百科文章中,您会找到几个用 Python 编写的解决方案。

更准确地说,您需要一个无界背包问题的解决方案,这与流行的 0/1 背包问题(每个元素只能打包一次)形成对比。这是来自 Rosetta 的工作代码:

from itertools import product


NAME, SIZE, VALUE = range(3)
items = (
    # NAME, SIZE, VALUE
    ('A', 3, 5),
    ('B', 5, 9),
    ('C', 9, 16))

capacity = 13


def knapsack_unbounded_enumeration(items, C):

    # find max of any one item
    max1 = [int(C / item[SIZE]) for item in items]
    itemsizes = [item[SIZE] for item in items]
    itemvalues = [item[VALUE] for item in items]

    # def totvalue(itemscount, =itemsizes, itemvalues=itemvalues, C=C):
    def totvalue(itemscount):
        # nonlocal itemsizes, itemvalues, C

        totsize = sum(n * size for n, size in zip(itemscount, itemsizes))
        totval = sum(n * val for n, val in zip(itemscount, itemvalues))

        return (totval, -totsize) if totsize <= C else (-1, 0)

    # Try all combinations of bounty items from 0 up to max1
    bagged = max(product(*[range(n + 1) for n in max1]), key=totvalue)
    numbagged = sum(bagged)
    value, size = totvalue(bagged)
    size = -size
    # convert to (iten, count) pairs) in name order
    bagged = ['%dx%d' % (n, items[i][SIZE]) for i, n in enumerate(bagged) if n]

    return value, size, numbagged, bagged


if __name__ == '__main__':
    value, size, numbagged, bagged = knapsack_unbounded_enumeration(items, capacity)
    print(value)
    print(bagged)

输出是:

23
['1x3', '2x5']

请记住,这是一个 NP-hard 问题,因此当您输入一些较大的值时它会失败 :)

关于python - 从较小的包裹中完成订单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54211693/

相关文章:

python - 正则表达式来匹配某些字符

python - 使用 pandas read_csv 检测导入 csv 文件的 header 分隔符

python - Jupyter Python3 内核安装 - 仅限离线

Python添加时间限制并检查自己是否已行动

python - 如何让我的 python 可执行文件找到我的网站包

python - 无法通过 wget e 或脚本访问 url

python - 如何将函数的返回值附加到池中的列表中?

python - 大于数组的值的 ndarray 行索引

python - 在 Python 中不关闭打开的文件会有什么后果?

Python 操作 json、列表和字典