【问题标题】:Why is my backtracking algorithm not working for this simple problem?为什么我的回溯算法不适用于这个简单的问题?
【发布时间】:2020-09-25 12:22:16
【问题描述】:

您好,我目前正在尝试解决以下问题:

假设您有一个随机排队的人列表。每个人由一对整数(h, k) 描述,其中h 是该人的身高,k 是此人面前身高大于或等于h 的人数。编写一个算法来重构队列。

注意: 人数不足1100人。

例子

Input:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

Output:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]

这是我目前的解决方案:

answer = []
def reconstructQueue(people):
    if len(answer) == len(people) and is_valid(answer):
        return True

    for person in people:
        answer.append(person)
        if is_valid(answer):
            reconstructQueue([x for x in people if x != person])
        else:
            answer.pop()




def is_valid(answer):
    answer = answer[::-1]
    for i in range(len(answer)):
        count = 0
        for j in answer[i+1:]:
            if answer[i][0] <= j[0]:
                count+=1
        if count != answer[i][1]:
            return False
    return True

我的is_valid 函数正在运行,但在recontructQueue 中实现的回溯出错了!

我认为它应该是这样工作的:

  • 检查我们是否有一个包含所有原始列表值的有效答案,如果是,我们就完成了。
  • 如果不是,则将其他人添加到列表中 answer 并查看是否有效。
  • 如果有效,则递归调用删除我们刚刚添加的元素的函数。
  • 如果它无效,那么我们就犯了一个错误,所以我们通过从答案中弹出该元素来回溯。

但它并没有给我正确的答案。

谁能帮忙解释一下我哪里出错了,我不擅长回溯!

谢谢。

【问题讨论】:

  • 您永远不会检查来自reconstructQueue 的返回值。您可以解决此问题,但在此之前您应该弄清楚您希望这需要多长时间。如果你有 1000 人,它可以永远运行。

标签: python algorithm recursion backtracking


【解决方案1】:

将全局 answer 作为递归内部工作的一部分并不是一个好主意。我们将用默认的第二个参数替换它。

正如@MattTimmermans 所说,您犯了递归初学者的错误,即让递归函数返回有用的结果,但在递归调用它时忽略了该结果。该递归调用将导致成功或失败,您需要采取相应措施:

def reconstructQueue(people, todo=None):
    if not todo and is_valid(people):
            return people

    if todo is None:
        todo = people
        people = []

    tossed = []

    while todo:
        people.append(todo.pop())

        if is_valid(people):
            result = reconstructQueue(people, todo + tossed)

            if result:
                return result

        tossed.append(people.pop())

    return None  # there is no solution from this starting point

def is_valid(answer):
    for index, (my_height, my_count) in enumerate(answer):
        their_count = sum(my_height <= their_height for their_height, _ in answer[:index])

        if their_count != my_count:
            return False

    return True

scrambled = [(7, 0), (4, 4), (7, 1), (5, 0), (6, 1), (5, 2)]

print(reconstructQueue(scrambled))

我还将您的数据结构从列表列表切换为元组列表,因为这对我来说更适合 Python。

输出

> python3 test.py
[(5, 0), (7, 0), (5, 2), (6, 1), (4, 4), (7, 1)]
>

【讨论】:

    猜你喜欢
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    相关资源
    最近更新 更多