python - 需要帮助编写通过数字列表找到最便宜路线的递归函数

标签 python recursion

所以我已经在这个家庭作业问题上工作了几个小时,我会尽力解释它。

我需要用 python 编写一个程序,它接受一个列表并从列表中的第一项开始,你可以向前移动一个空格或跳过一个项目并落在它的另一边,每个项目你land on 花费那个位置的数字。目标是以尽可能低的成本到达终点。

我写了这个函数,

def player(cost, board, player_pos):
    if player_pos == (len(board)) - 1:    
        return cost
    if player_pos < (len(board)) - 2:     
        if board[player_pos + 1] > board[player_pos + 2]:
            return player(cost + board[player_pos + 2], board, player_pos + 2)
        else:
            return player(cost + board[player_pos + 1], board, player_pos + 1)
    elif player_pos == (len(board)) - 2:
        return (cost + board[player_pos] + board[player_pos + 1])

但它无法看到接下来的两个位置,所以它可能会出错。一个很好的例子是这个列表 [0,1,2,1000,0] 我的程序输出 3,因为它从 2 中选择 1,然后从 1000 中选择 2,然后是 0。这加起来是 3,但最快的方法是跳转到2,然后到0。

在家庭作业中它说运行长列表可能需要很长时间,我猜他们希望我尝试所有可能的跳跃组合并选择最便宜的,但我不知道如何使用递归。

编辑: 所以这是我根据评论所做的改进,它适用于我教授的所有示例。给了我一个,这是一个列表,它没有返回他所说的应该返回的内容。 [0, 98, 7, 44, 25, 3, 5, 85, 46, 4] 他说它应该返回 87,但我调整后的程序返回 124。这是新代码:

def player(cost, board, player_pos):
    if player_pos == (len(board)) - 1:    
        return cost
    if player_pos < (len(board)) - 2:     
        if (player(cost + board[player_pos + 2], board, player_pos + 2)) < (player(cost + board[player_pos + 1], board, player_pos + 1)):
            return player(cost + board[player_pos + 2], board, player_pos + 2)
        else: return player(cost + board[player_pos + 1], board, player_pos + 1)
    elif player_pos == (len(board)) - 2:
        return (cost + board[player_pos] + board[player_pos + 1])

最佳答案

以下应该有效:

def player(l):
    a = b = l[0]
    for v in l[1:]:
        a, b = b, min(a, b) + v
    return b

例子:

>>> player([0, 98, 7, 44, 25, 3, 5, 85, 46, 4])
87

这实际上可以认为是一个dynamic programming算法。如果 c(i) 表示使用第一个 i 条目的子问题的最佳成本,则:

c(1) = cost of first element

c(2) = sum of costs of first two elements

对于 i > 2 要么最佳成本要么是达到第 i - 1 个元素然后包括第 i 个的最佳解决方案元素或到达第 i - 2 元素然后跳转到第 i 元素的最佳解决方案。所以

c(i) = min(c(i - 1), c(i - 2)) + cost of ith element

上面的关系解释了代码中的短循环,其中ab是当前最后两个最好的代价。

递归版本是这样的:

def player(l):
    return min(player(l[:-1]), player(l[:-2])) + l[-1] if l else 0

此递归程序对函数的前 2 个值执行操作,其方式与斐波那契的朴素递归函数类似。很容易声称上述版本也需要指数时间。为了避免它,我们应该使用 memoization ,这意味着缓存中间递归调用的结果:

def player(l, cache=None):
    n = len(l)
    if cache is None:
        cache = [-1] * (n + 1)
    if cache[n] < 0:
        cache[n] = min(player(l[:-1], cache), player(l[:-2], cache)) + l[-1] if l else 0
    return cache[n]

关于python - 需要帮助编写通过数字列表找到最便宜路线的递归函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29684981/

相关文章:

java - 给定一个整数 a 列表,使用递归返回一个新列表,其中包含 a 的所有正元素

python - 突变后更新动态依赖的对象属性

python - 如何在 Python 中创建多个 for 列表循环的递归以获得组合?

javascript - (非常简单的递归)我错过了什么?

javascript - 从单个方程输出/生成一组点 - Python、JS、Matlab

JavaScript:递归深度比较:对象和属性

python __getattribute__ 返回类变量属性时出现RecursionError

python脚本在sublime text中打开文件

python - 对数据框的行进行排序并更改每隔一行的值时出现问题

python - 生成包含数组元素的每个组合的数组