Python 3.x 求非连续元素的最小和

Python 3.x 求非连续元素的最小和,python-3.x,recursion,memoization,Python 3.x,Recursion,Memoization,我试图找到列表中非连续元素的最小和, 每次我都可以跳过一个或两个细胞。 第一个单元格不计入总和 实现必须包括递归和记忆。我试图实现这样的方法,但不幸的是,它实际上并没有使用记忆,而且在一些示例中也不起作用 我的代码如下所示: def optimal_cruise_seasick(toilet_prices): prices_dict = {} return optimal_cruise_seasick_mem(toilet_prices, 0, len(toilet_prices

我试图找到列表中非连续元素的最小和, 每次我都可以跳过一个或两个细胞。 第一个单元格不计入总和

实现必须包括递归和记忆。我试图实现这样的方法,但不幸的是,它实际上并没有使用记忆,而且在一些示例中也不起作用

我的代码如下所示:

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
def最佳巡航晕船(厕所价格):
价格_dict={}
返回最佳邮轮、晕船、记忆(马桶价格、0、len(马桶价格)、价格
def optimal_cruise_Seask_mem(价格、起点、终点、dic):
如果驾驶员信息中心中有(开始、结束):
返回dic[(开始,结束)]
如果(开始+1==结束或开始+2==结束):
退货价格表[end-1]
最低成本=价格(1月底)
i=开始+1
而(i坦白地说,如果(一个你的实现是令人困惑的。我已经写了一个正确工作的替代实现(根据你在评论中的澄清),尽管我不知道它是否以你想要的方式记录

我们要做的是从价目表中的第一个“实际”的东西开始(去掉第一个元素;在你的例子中是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
正如你们所看到的,它是在记忆价格表的后缀


我应该补充一点,你可以用更简洁的方式实现同样的效果。这里的
f2
相当于上面的
f
(如果你的价目表足够短,所有东西都可以放入缓存),除了你没有为
memo
传递
dict()

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:]))

您未明确说明您的问题。40、100、30是否为合法顺序?(从40开始,跳过2100、跳过2、30、跳过2、列表末尾。)如果你根本不算总数中的20,为什么你不从价格表的第一个元素开始删掉呢?@Galc127,你能再增加一些预期的输出吗?现在我看看你的代码,当你说“非连续”时,我明白了在标题中,您实际上并不是指非连续,因为您实际上可以将列表中的连续元素计入总和。@senshin,它不是跳过,而是转到,因此从40移动到单元格就是转到80。例如,法律顺序可能是(从40开始,移动2,80,移动1,100,移动2,50,移动2,10,移动1,30,结束)。好的,那么40,80,70,30,10-这会产生230?这合法吗?(从40开始,移动2,80,移动2,70,移动2,30,移动1,10,移动2,30,移动1,10,移动2,列表结束)不幸的是,代码不起作用。对于[50,30,10,30],它返回60而不是40(10,30)@Galc127,
10,30
是连续的,那么这怎么可能是答案呢?@padraiccnningham,50不算在内,因此我们移动两步,支付10,然后移动一步,支付30。我们总共支付了40。@Galc127,所以最后的元素可以是连续的?@padraiccnningham,你可以随时移动一步或两步。如果获得最少的付款,by每次只进行一步,则结果应为除第一个元素外的所有列表。