这个问题与经典的0-1背包问题大致相同,但是会有一些小的规则变化和大数据集。
数据集(产品ID,价格,长度,宽度,高度,重量): (20,000行)
问题:
一家公司正在快速交付第100万笔订单。营销团队决定将作出该订单的客户作为赞赏的姿态。奖品是:幸运的顾客在仓库中获得一个交货手提包和1小时。用小时填充你想要的任何产品的手提包,然后免费带回家。
规则:
每个项目中的1个
组合体积<手提袋容量(45 * 30 * 25 = 47250)
物品必须单独放置(尺寸可以放入手提包中,例如45 * 45 * 1不适合)
最大化组合产品的价值
最大限度地减少抽签的重量
解决方案(使用动态编程):
from functools import reduce
# The main solver function
def Solver(myItems, myCapacity):
dp = {myCapacity: (0, (), 0)}
getKeys = dp.keys
for i in range(len(myItems)):
itemID, itemValue, itemVolume, itemWeight = myItems[i]
for oldVolume in list(getKeys()):
newVolume = oldVolume - itemVolume
if newVolume >= 0:
myValue, ListOfItems, myWeight = dp[oldVolume]
node = (myValue + itemValue, ListOfItems + (itemID,), myWeight + itemWeight)
if newVolume not in dp:
dp[newVolume] = node
else:
currentValue, loi, currentWeight = dp[newVolume]
if currentValue < node[0] or (currentValue == node[0] and node[-1] < currentWeight):
dp[newVolume] = node
return max(dp.values())
# Generate the product of all elements within a given list
def List_Multiply(myList):
return reduce(lambda x, y: x * y, myList)
toteDims = [30, 35, 45]
totalVolume = List_Multiply(toteDims)
productsList = []
with open('products.csv', 'r') as myFile:
for myLine in myFile:
myData = [int(x) for x in myLine.strip().split(',')]
itemDims = [myDim for myDim, maxDim in zip(sorted(myData[2:5]), toteDims) if myDim <= maxDim]
if len(itemDims) == 3:
productsList.append((myData[0], myData[1], List_Multiply(myData[2:5]), myData[5]))
print(Solver(productsList, totalVolume))
问题:
输出正在重复项目
即。 (14018, (26, 40, 62, 64, 121, 121, 121, 152, 152), 13869)
如何纠正此问题,使其只选择每个项目中的一个?
答案 0 :(得分:1)
看起来您的代码可能会产生重复项的答案的原因是,在内部循环中,当您到目前为止迭代所有生成的卷时,代码可能已经替换了现有卷值的解决方案我们到了那里。
E.g。如果您的sudo resize2fs /dev/xvda1
包含以下内容
productsList
和
productsList = [
# id, value, volume, weight
[1, 1, 2, 1],
[2, 1, 3, 2],
[3, 3, 5, 1]
]
然后当你到达第三个项目时,totalVolume = 10
将包含:
dp.keys()
不保证迭代的顺序,但是为了这个例子,我们假设它如上所述。然后10, 8, 7, 5
将被包含项目#3的新解决方案所取代,稍后在迭代中,我们将使用它作为新的,更好的解决方案的基础(现在除了重复项目)。
为了克服上述问题,您可以在迭代之前对其进行排序(按升序排列,这是默认值),如dp[5]
。假设所有项目都具有非负数量,这应该保证我们在迭代它之前永远不会替换for oldVolume in sorted(getKeys())
中的解决方案。
我在上面看到的另一个可能的问题是我们使用dp
在最后获得最佳解决方案的方式。在问题陈述中,它表示我们希望在平局的情况下最小化重量。如果我正确读取代码,元组的元素按顺序是 value ,项目列表, weight ,所以下面我们为价值而束缚,但后者的选择会更好,因为权重较小......但是max(dp.values())
会返回第一个:
max
可以将排序键指定为>>> max([(4, (2, 3), 3), (4, (1, 3), 2)])
(4, (2, 3), 3)
,这样可能会起作用:
max