最近遇见一个背包问题,scores = [15,10,9,5]和weitghts = [1,5,3,4]列表长度一致,如果背包重量为8,则最优解是29,weitghts中1+3+4的重量对应的分数和(15+9+5)=29,其实不难,但是大部分推荐贪婪算法,但是好多贪婪算法,个别重量可重复或者可分割,考虑了半天,做出来了一个类似穷举法的方法求最优解,其实还有优化的地方,例如再次输入,如果scores和weitghts没变过,单独求背包重量最优解,我的final_price_list只需要保存最初那次字典即可等等。
import itertools as it
scores = [15,10,9,5]
weitghts = [1,5,3,4]
#根把weight做成一个字典
weight_index_dict1 = dict(enumerate(weitghts))
#再把字典键值对反转,这样通过key可以对应scores的下标
weight_index_dict2 = {k:v for v,k in weight_index_dict1.items()}
dict_value = {}
price_list = []
#迭代所有组合,
def iterall(weitghts:list,cap = 8):
for i in range(1,len(weitghts)+1):
iternum(weitghts,i)
get_max(cap)#迭代某个组合,例如num=3,得到(1,5,3)、(1,5,4)、(5,3,4)组合
def iternum(weitghts:list,num:int):
for item in it.combinations(weitghts,num):
total_weight = 0
temp_price = 0
for index,value in enumerate(item):
total_weight += value
temp_price += get_index(value)
add_dict(total_weight,temp_price)#这里做了一个反字典,通过weights的值,得到对应的下标,进而得到scores对应的分数
def get_index(key):
index = weight_index_dict2[key]
return scores[index]#做了一个字典集合,把所有组合放进一个字典,例如重量8,可以1+3+4也可以5+3,分数分别是15+9+4和10+9,但是如果键值存在(8),则判断,如果key大于原来的key,才会覆盖,如果是新key,则添加
def add_dict(key,value):
if key in dict_value:
if value > dict_value[key]:
dict_value[key] = value
else:
dict_value.update({key:value})#dict_value已经把所有的重量组合以及对应的分数拿到,即重量1,最优就是15分,{1: 15, 5: 20, 3: 9, 4: 24, 6: 25, 8: 29, 9: 34, 7: 14, 10: 30, 12: 24, 13: 39}
#这里有个问题,如果背包是3 ,则最优解反而是装weights[0],背包装到1则足够得到15分,而不是3
def get_max(cap:int):
final_price_list = []
for k,v in dict_value.items():
if k<=cap:
final_price_list.append(v)
print(final_price_list)
max_price = max(final_price_list)
print(max_price)
return max_priceif __name__ == '__main__':
iterall(weitghts,3)
文章介绍了一种解决背包问题的方法,针对给定的scores和weights列表,通过穷举所有可能的物品组合,找到在不超过背包重量限制下的最大分数。文中提到,虽然贪心算法通常被推荐,但此问题不适合贪心策略,因此采用了一种基于字典和组合的穷举策略。代码实现了根据物品重量和分数计算最优解,并能处理已知输入不变时的重复计算优化。
3627

被折叠的 条评论
为什么被折叠?



