Python中的贪心算法
我希望掠夺中的c(aList,c)等于0Python中的贪心算法,python,list,sorting,tuples,greedy,Python,List,Sorting,Tuples,Greedy,我希望掠夺中的c(aList,c)等于0 List = [('Gold', 10, 500), ('Silver', 5, 200), ('Diamond', 2, 2000), ('Platinum', 20, 1000)] aList = sorted(List, key = lambda x : x[2]) # sort the list above 根据每个元组的第三个值给出排序列表。所以我得到: [('Silver', 5, 200), ('Gold', 10, 500), ('P
List = [('Gold', 10, 500), ('Silver', 5, 200), ('Diamond', 2, 2000), ('Platinum', 20, 1000)]
aList = sorted(List, key = lambda x : x[2]) # sort the list above
根据每个元组的第三个值给出排序列表。所以我得到:
[('Silver', 5, 200), ('Gold', 10, 500), ('Platinum', 20, 1000), ('Diamond', 2, 2000)]
我试图让掠夺(aList,c)不断地从c中减去每个元组(2,20,10,5)的中间值,直到c=0
这是我的密码:
List = [('Gold', 10, 500), ('Silver', 5, 200), ('Diamond', 2, 2000), ('Platinum', 20, 1000)]
aList = sorted(List, key = lambda x : x[2]) # sort the list above
def plunder(aList, c):
aList[-1] = list(aList[-1])
i = aList[-1]
r = 0
if c > 0 and i[1] != 0:
c -= 1
i[1] -=1
r += 1
return plunder(aList, c-r)
elif c == 0:
pass
print('Done')
else:
return plunder(aList[:-1], c-r)
plunder(aList, 10)
但当我运行它时,它会打印“完成”,新列表是:
[('Silver', 5, 200), ('Gold', 10, 500), ('Platinum', 20, 1000), ['Diamond', 0, 2000]]
当我在pythonshell中输入c时,它告诉我c没有定义。我如何解决这些问题
如果c值是10。我的预期产出是:
[('Silver', 5, 200), ('Gold', 10, 500), ['Platinum', 12, 1000], ['Diamond', 0, 2000]]
我从10颗钻石中减去尽可能多的钻石(10-2=8),所以剩下0颗钻石。然后我从20个platinums中减去8,platinums的重量变为12(因为我得到了8个platinums。现在我的c(“容量”)是0.2菱形+8个platinums=10(这是我的c)。主要的问题是,您依赖Python的pass by reference来修改列表。 这在一开始很好,但当你到达
plunder(aList[:-1], c-r)
Python创建列表的副本,并继续修改该副本。因此,在钻石耗尽后,原始列表保持不变(您点击其他
部分)
请注意,您可以在打印的列表中看到这种行为,因为只有最后一个条目是列表
,而所有其他条目都是元组
[
('Silver', 5, 200),
('Gold', 10, 500),
('Platinum', 20, 1000),
['Diamond', 0, 2000] #Only list
]
如果将print alist[-1]
语句添加到函数中,您可以更清楚地看到它
['Diamond', 2, 2000]
['Diamond', 1, 2000]
['Diamond', 0, 2000]
['Platinum', 20, 1000]
['Platinum', 19, 1000]
['Platinum', 18, 1000]
['Platinum', 17, 1000]
['Platinum', 16, 1000]
['Platinum', 15, 1000]
['Platinum', 14, 1000]
['Platinum', 13, 1000]
['Platinum', 12, 1000]
因此,您的算法确实有效,但由于无法保留结果,因此不会(完全)影响原始列表。主要问题是,您依赖Python的列表传递引用来修改列表。
这在一开始很好,但当你到达
plunder(aList[:-1], c-r)
Python创建列表的副本,并继续修改该副本。因此,在钻石耗尽后,原始列表保持不变(您点击其他
部分)
请注意,您可以在打印的列表中看到这种行为,因为只有最后一个条目是列表
,而所有其他条目都是元组
[
('Silver', 5, 200),
('Gold', 10, 500),
('Platinum', 20, 1000),
['Diamond', 0, 2000] #Only list
]
如果将print alist[-1]
语句添加到函数中,您可以更清楚地看到它
['Diamond', 2, 2000]
['Diamond', 1, 2000]
['Diamond', 0, 2000]
['Platinum', 20, 1000]
['Platinum', 19, 1000]
['Platinum', 18, 1000]
['Platinum', 17, 1000]
['Platinum', 16, 1000]
['Platinum', 15, 1000]
['Platinum', 14, 1000]
['Platinum', 13, 1000]
['Platinum', 12, 1000]
因此,您的算法确实有效,但由于您无法保留结果,因此它不会(完全)影响您的原始列表。我认为这是一种更简单的方法。只需在可用的宝藏中进行迭代,并从每一个宝藏中获取尽可能多的信息
def demo():
units_to_plunder = 10
treasure = new_treasure_pile()
plundered_units = plunder_units(treasure, units_to_plunder)
print treasure
print plundered_units
units_to_plunder = 1000
treasure = new_treasure_pile()
plundered_units = plunder_units(treasure, units_to_plunder)
print treasure
print plundered_units
def plunder_units(treasure, total_plunder_units):
treasure_sorted = list(sorted(treasure, key=lambda t: t[2], reverse=True))
plundered = list()
for treasure_type in treasure_sorted:
# stop condition when desired units taken
if total_plunder_units <= 0:
break
t_units_to_take = min(total_plunder_units, treasure_type[1])
# update the 3 moving parts
treasure_type[1] -= t_units_to_take
plundered.append([treasure_type[0], t_units_to_take, treasure_type[2]])
total_plunder_units -= t_units_to_take
return plundered
def new_treasure_pile():
return [['Gold', 10, 500],
['Silver', 5, 200],
['Diamond', 2, 2000],
['Platinum', 20, 1000]]
if __name__ == '__main__':
demo()
c=1000的输出(全部接受)
我认为这是一个更简单的方法。只需在可用的宝藏中迭代,并从每个宝藏中获取尽可能多的信息
def demo():
units_to_plunder = 10
treasure = new_treasure_pile()
plundered_units = plunder_units(treasure, units_to_plunder)
print treasure
print plundered_units
units_to_plunder = 1000
treasure = new_treasure_pile()
plundered_units = plunder_units(treasure, units_to_plunder)
print treasure
print plundered_units
def plunder_units(treasure, total_plunder_units):
treasure_sorted = list(sorted(treasure, key=lambda t: t[2], reverse=True))
plundered = list()
for treasure_type in treasure_sorted:
# stop condition when desired units taken
if total_plunder_units <= 0:
break
t_units_to_take = min(total_plunder_units, treasure_type[1])
# update the 3 moving parts
treasure_type[1] -= t_units_to_take
plundered.append([treasure_type[0], t_units_to_take, treasure_type[2]])
total_plunder_units -= t_units_to_take
return plundered
def new_treasure_pile():
return [['Gold', 10, 500],
['Silver', 5, 200],
['Diamond', 2, 2000],
['Platinum', 20, 1000]]
if __name__ == '__main__':
demo()
c=1000的输出(全部接受)
您可以发布您的预期输出吗?也就是说,您希望列表的结尾是什么样子?第5行中的aList[-1]=list(aList[-1]
的要点是什么?aList[-1]=list(aList[-1]将元组转换为列表。因为我可以更改列表中的元素,但不能更改元组中的元素。我认为这可能是您的问题。当您键入aList[-1]=list(aList[-1])
时,现在aList有一个列表-即['Diamond',22000]
-作为它的最后一个元素。这应该是一个元组。对吗?这看起来像背包问题,权重被替换为文章数。请发布您的预期输出?也就是说,您希望列表的结尾是什么样子?第5行中的aList[-1]=list(aList[-1]
的意义是什么?aList[-1]的意义是什么=列表(aList[-1]是将元组转换为列表。因为我可以更改列表中的元素,但不能更改元组中的元素。我认为这可能是您的问题。当您键入aList[-1]=列表(aList[-1])
时,现在aList有一个列表-即['Diamond',22000]
-作为它的最后一个元素。这应该是一个元组。对吗?这看起来像是背包问题,权重被ArticleNumber替换。我想补充一点,函数从基本情况中不返回任何内容,因此结果不能沿调用堆栈累积。我想补充一点,函数从基本情况中不返回任何内容,因此,结果不能沿调用堆栈累积。