如何解决Python返回适合设置参数的项目列表
我在将返回的解决方案正确装箱到min_cals时遇到一些困难。
menu = [
{'name':'Cheese Pizza Slice','calories': 700,'cost': 4},{'name':'House Salad','calories': 100,'cost': 8.5},{'name':'Grilled Shrimp','calories': 400,'cost': 15},{'name':'Beef Brisket','cost': 12},{'name':'Soda','cost': 1},{'name':'Cake','calories': 300,'cost': 3},]
def menu_recommendation(menu,min_cal,max_cal,budget):
menu = [item for item in menu if item['calories'] <= max_cal and item['cost'] <= budget]
if len(menu) == 0: return []
return min((
[item] + menu_recommendation(menu,min_cal - item['calories'],max_cal - item['calories'],budget - item['cost'])
for item in menu
),key=
lambda recommendations: [budget - sum(item['cost'] for item in recommendations) and min_cal <= sum(item['calories'] for item in recommendations) <= max_cal,-sum(item['calories'] for item in recommendations)]
)
recommendation = menu_recommendation(menu,1000,1200,15)
total_cost = sum(item['cost'] for item in recommendation)
total_cals = sum(item['calories'] for item in recommendation)
print(f'recommendation: {recommendation}')
print(f'total cost: {total_cost}')
print(f'total calories: {total_cals}')
例如,以下代码返回总热量为700(低于最小值1000)的解决方案。 推荐= menu_recommendation(菜单,1000,1200,15)
解决方法
我们可以递归地进行一些工作。
def smallest_combo(lst,m,n,z):
# filter list to remove elements we can't use next without breaking the rules
lst = [dct for dct in lst if m <= dct['x'] <= n and dct['y'] <= z]
# recursive base case
if len(lst) == 0:
return []
# go through our list of eligibles
# simulate 'what would the best possibility be if we picked that one to go with next'
# then of those results select the one with the sum('y') closest to z
# (breaking ties with the largest sum('x'))
return min((
[dct] + smallest_combo(lst,m - dct['x'],n - dct['x'],z - dct['y'])
for dct in lst
),key=
lambda com: [z - sum(d['y'] for d in com),-sum(d['x'] for d in com)]
)
inp = [{'name': 'item1','x': 600,'y': 5},{'name': 'item2','x': 200,'y': 8},{'name': 'item3','x': 500,'y': 12.5},{'name': 'item4','x': 0,'y': 1.5},{'name': 'item5','x': 100,'y': 1}]
print(smallest_combo(inp,500,1500,25))
# [{'name': 'item3','y': 12.5}]
有多种方法可以加快此过程。首先是建立递归缓存,其次是采用动态编程方法(即从底部开始而不是从顶部开始)。
,这是一个动态编程解决方案,它建立一个数据结构,显示我们可以使用的所有(calorie,cost)
选项以及每个选项。我们会寻找符合标准的最佳人选,然后找到建议。
def menu_recommendation(menu,min_cal,max_cal,budget):
# This finds the best possible solution in pseudo-polynomial time.
recommendation_tree = {(0,0.0): None}
for item in menu:
# This tree will wind up being the old plus new entries from adding this item.
new_recommendation_tree = {}
for key in recommendation_tree.keys():
calories,cost = key
new_recommendation_tree[key] = recommendation_tree[key]
new_key = (calories + item['calories'],cost + item['cost'])
if new_key not in recommendation_tree and new_key[0] <= max_cal:
# This is a new calorie/cost combination to look at.
new_recommendation_tree[new_key] = item
# And now save the work.
recommendation_tree = new_recommendation_tree
# Now we look for the best combination.
best = None
for key in recommendation_tree:
calories,cost = key
# By construction,we know that calories <= max_cal
if min_cal <= calories:
if best is None or abs(budget - cost) < abs(budget - best[1]):
# We improved!
best = key
if best is None:
return None
else:
# We need to follow the tree back to the root to find the recommendation
calories,cost = best
item = recommendation_tree[best]
answer = []
while item is not None:
# This item is part of the menu.
answer.append(item)
# And now find where we were before adding this item.
calories = calories - item['calories']
cost = cost - item['cost']
best = (calories,cost)
item = recommendation_tree[best]
return answer
,
我想到了这一点,它基本上是背包,但是如果不适合推荐,它将从菜单中递归删除菜品
menu = [
{'name':'Cheese Pizza Slice','calories': 700,'cost': 4},{'name':'House Salad','calories': 100,'cost': 8.5},{'name':'Grilled Shrimp','calories': 400,'cost': 15},{'name':'Beef Brisket','cost': 12},{'name':'Soda','cost': 1},{'name':'Cake','calories': 300,'cost': 3},]
def get_price(recommendation):
return sum(dish["cost"] for dish in recommendation)
def get_calories(recommendation):
return sum(dish["calories"] for dish in recommendation)
def menu_recommendation(menu,budget):
sorted_menu = sorted(menu,key=lambda dish: dish["cost"],reverse=True)
recommendation = []
for dish in sorted_menu:
if dish["cost"] + get_price(recommendation) <= budget:
recommendation.append(dish)
if recommendation:
if get_calories(recommendation) < min_cal:
sorted_menu.remove(min(recommendation,key=lambda dish: dish["calories"]/dish["cost"]))
return menu_recommendation(sorted_menu,budget)
if get_calories(recommendation) > max_cal:
sorted_menu.remove(max(recommendation,budget)
return recommendation
recommendation = menu_recommendation(menu,800,15)
total_cost = sum(item['cost'] for item in recommendation)
total_cals = sum(item['calories'] for item in recommendation)
print(f'recommendation: {recommendation}')
print(f'total cost: {total_cost}')
它根据卡路里/成本比率删除元素,因为这是背负背包的成本。
如有任何疑问,请告诉我。
,我相信我已经解决了提出超出min_cal / max_cal范围的建议的问题,但是我仍然觉得可能存在一种更接近预算的解决方案。
这是我更新的代码:
menu = [
{'name':'Cheese Pizza Slice',]
def menu_recommendation(menu,budget):
menu = [item for item in menu if item['calories'] <= max_cal and item['cost'] <= budget]
if len(menu) == 0: return []
return min(([item] + menu_recommendation(menu,min_cal - item['calories'],max_cal - item['calories'],budget - item['cost'])
for item in menu
),key=
lambda recommendations: [budget - sum(item['cost'] for item in recommendations)
and min_cal - sum(item['calories'] for item in recommendations) >= 0
and max_cal - sum(item['calories'] for item in recommendations) >= 0,-sum(item['calories'] for item in recommendations)]
)
recommendation = menu_recommendation(menu,1000,1200,15)
total_cost = sum(item['cost'] for item in recommendation)
total_cals = sum(item['calories'] for item in recommendation)
print(f'recommendation: {recommendation}')
print(f'total cost: {total_cost}')
print(f'total calories: {total_cals}')
如果有人有任何改进,我希望听到他们的声音!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。