我试图在列表中找到非连续元素的最小总和, 每次我可以跳一个细胞或两个细胞。 第一个单元格不计入总和。
实现必须包括递归和memoization 。我试图实现这样的方法,但不幸的是,它实际上并没有使用memoization,它也不适用于某些例子。
我的代码如下所示:
def optimal_cruise_seasick(toilet_prices):
prices_dict = {}
return optimal_cruise_seasick_mem(toilet_prices, 0, len(toilet_prices), prices_dict)
def optimal_cruise_seasick_mem(prices_lst, start, end, dic):
if (start,end) in dic:
return dic[(start,end)]
if(start + 1 == end or start + 2 == end):
return prices_lst[end-1]
min_cost = prices_lst[end-1]
i = start + 1
while(i < end - 1):
one = optimal_cruise_seasick_mem(prices_lst, i, i+1, dic)
two = optimal_cruise_seasick_mem(prices_lst, i, i+2, dic)
if (one <= two):
min_cost += one
i += 1
else:
min_cost += two
i += 2
dic[(start,end)] = min_cost
return min_cost
我试图为toilet_prices = [20,40,60,80,100,70,50,30,10,30]
运行它。
它返回320而不是250(40,80,70,30,30)。我应该如何修复我的代码,以便它能够按要求工作?
谢谢!
答案 0 :(得分:3)
我们所做的是从价格清单中的第一个“实际”事物开始(剥离第一个元素;在你的例子中,20个),然后连续看到切掉左边的一个或左边的两个元素给我们一个较低的金额。
def f(prices, memo):
if prices not in memo:
if len(prices) == 1:
memo[prices] = prices[0]
elif len(prices) == 2:
# We must include the final cell in the list, but can choose to get there
# either by two 1-moves or one 2-move. Obviously the one 2-move is going
# to be non-pessimal if all prices are non-negative, but we'll put the min
# call in here for elucidation/explicitness anyway.
memo[prices] = min(prices[1], prices[0] + prices[1])
else:
memo[prices] = prices[0] + min(f(prices[1:], memo), f(prices[2:], memo))
return memo[prices]
def optimal_cruise_seasick(prices):
return f(prices[1:], dict())
添加一些打印语句以指示我们何时从备忘录中读取:
>>> optimal_cruise_seasick((20,40,60,80,100,70,50,30,10,30))
Read from memo: (10, 30) -> 30
Read from memo: (30, 10, 30) -> 60
Read from memo: (50, 30, 10, 30) -> 80
Read from memo: (70, 50, 30, 10, 30) -> 130
Read from memo: (100, 70, 50, 30, 10, 30) -> 180
Read from memo: (80, 100, 70, 50, 30, 10, 30) -> 210
250
正如您所看到的,它会记住价格表的后缀。
我应该补充一点,你可以使用functools.lru_cache
以更干净的方式达到同样的效果。这里的f2
相当于上面的f
(如果您的价格表足够短,所有内容都适合缓存),除了您没有为{dict()
传递memo
1}},显然。
from functools import lru_cache
@lru_cache()
def f2(prices):
if len(prices) == 1:
return prices[0]
elif len(prices) == 2:
return min(prices[1], prices[0] + prices[1])
else:
return prices[0] + min(f2(prices[1:]), f2(prices[2:]))