我正在编写一个贪婪算法(Python 3.x.x)用于'宝石抢劫'。鉴于一系列珠宝和价值,该计划抓住了它可以放入袋子里的最有价值的宝石,而不超过袋子重量限制。我在这里有三个测试用例,它适用于其中两个。
每个测试用例都以相同的方式编写:第一行是行李重量限制,后面的所有行都是元组(重量,值)。
示例案例1(正常):
10
3 4
2 3
1 1
示例案例2(不起作用):
575
125 3000
50 100
500 6000
25 30
代码:
def take_input(infile):
f_open = open(infile, 'r')
lines = []
for line in f_open:
lines.append(line.strip())
f_open.close()
return lines
def set_weight(weight):
bag_weight = weight
return bag_weight
def jewel_list(lines):
jewels = []
for item in lines:
jewels.append(item.split())
jewels = sorted(jewels, reverse= True)
jewel_dict = {}
for item in jewels:
jewel_dict[item[1]] = item[0]
return jewel_dict
def greedy_grab(weight_max, jewels):
#first, we get a list of values
values = []
weights = []
for keys in jewels:
weights.append(jewels[keys])
for item in jewels.keys():
values.append(item)
values = sorted(values, reverse= True)
#then, we start working
max = int(weight_max)
running = 0
i = 0
grabbed_list = []
string = ''
total_haul = 0
# pick the most valuable item first. Pick as many of them as you can.
# Then, the next, all the way through.
while running < max:
next_add = int(jewels[values[i]])
if (running + next_add) > max:
i += 1
else:
running += next_add
grabbed_list.append(values[i])
for item in grabbed_list:
total_haul += int(item)
string = "The greedy approach would steal $" + str(total_haul) + " of
jewels."
return string
infile = "JT_test2.txt"
lines = take_input(infile)
#set the bag weight with the first line from the input
bag_max = set_weight(lines[0])
#once we set bag weight, we don't need it anymore
lines.pop(0)
#generate a list of jewels in a dictionary by weight, value
value_list = jewel_list(lines)
#run the greedy approach
print(greedy_grab(bag_max, value_list))
有没有人有任何线索为什么它不适用于案例2?非常感谢您的帮助。 编辑:案例2的预期结果是6130美元。我好像得到了6090美元。
答案 0 :(得分:2)
您的字典键是字符串,而不是整数,因此当您尝试对它们进行排序时,它们会按字符串排序。所以你会得到:
['6000', '3000', '30', '100']
反而想要:
['6000', '3000', '100', '30']
将此函数更改为此类并具有整数键:
def jewel_list(lines):
jewels = []
for item in lines:
jewels.append(item.split())
jewels = sorted(jewels, reverse= True)
jewel_dict = {}
for item in jewels:
jewel_dict[int(item[1])] = item[0] # changed line
return jewel_dict
当你改变它时它会给你:
The greedy approach would steal $6130 of jewels.
答案 1 :(得分:1)
In [237]: %paste
def greedy(infilepath):
with open(infilepath) as infile:
capacity = int(infile.readline().strip())
items = [map(int, line.strip().split()) for line in infile]
bag = []
items.sort(key=operator.itemgetter(0))
while capacity and items:
if items[-1][0] <= capacity:
bag.append(items[-1])
capacity -= items[-1][0]
items.pop()
return bag
## -- End pasted text --
In [238]: sum(map(operator.itemgetter(1), greedy("JT_test1.txt")))
Out[238]: 8
In [239]: sum(map(operator.itemgetter(1), greedy("JT_test2.txt")))
Out[239]: 6130
答案 2 :(得分:0)
我认为在这段代码中i
也必须在其他方面增加
while running < max:
next_add = int(jewels[values[i]])
if (running + next_add) > max:
i += 1
else:
running += next_add
grabbed_list.append(values[i])
i += 1 #here
这和@ iblazevic的答案解释了为什么它的表现如此