2

我正在尝试创建一个函数来在有向图中找到最高分。我确实有一个起始节点,不能两次通过同一个节点。我尝试使用递归来获取值的总和,直到我到达一个末端节点。然后我会将我的函数回调到起始节点并尝试其他选项,直到我遇到另一个选项。等等。

我的问题是,当我返回具有多个路径的节点时,该节点的得分值是它可以采用的所有路径的总和。我只想要一条特定路径的总和。

到目前为止,这是我的代码:


caminho = list()
def maxscore(start, parentals, score):
    global caminho
    parentals += start + '|'

    if len(graph[start]) > 0:
        for i in graph[start]:
            if i not in parentals.split('|'):
                value = graph[start][i]
                if value:
                    score += value

                func = maxscore(i, parentals, score)

            else:
                continue

        if func[0] > score:
            score = func[0]
            caminho = parentals.split('|')

        return score, caminho

    else:
        return score, start

graph = {
    'a': {'b': 2, 'c': 4},
    'b': {'d': 5},
    'c': {'a': 1, 'e': 3},
    'd': {'f': 4},
    'e': {'b': 2, 'f': 3, 'g': 2},
    'f': {},
    'g': {}
}

print(maxscore('a', '', 0))

我怎样才能让它最终只用它所走的路径(caminho)返回最好的分数。

对不起,如果我不能让自己足够清楚。随意问任何问题。

4

2 回答 2

2

您可能希望按值发送分数变量,但您是通过引用发送它,因此所有可能路径的分数都添加到它。

这是我的方法:

def maxscore(start, parentals, score):
    newParentals = parentals + start + '|'
    print newParentals, score
    scores = []
    if graph[start]:
        for nextNode in graph[start]:
            if nextNode not in newParentals.split('|'):
                scores.append(maxscore(nextNode, newParentals, score + graph[start][nextNode]))
        return sorted(scores)[-1]
    else:
        return score

graph = {
    'a': {'b': 2, 'c': 4},
    'b': {'d': 5},
    'c': {'a': 1, 'e': 3},
    'd': {'f': 4},
    'e': {'b': 2, 'f': 3, 'g': 2},
    'f': {},
    'g': {}
}

print(maxscore('a', '', 0))

这就是打印出来的:

a| 0
a|c| 4
a|c|e| 7
a|c|e|b| 9
a|c|e|b|d| 14
a|c|e|b|d|f| 18
a|c|e|g| 9
a|c|e|f| 10
a|b| 2
a|b|d| 7
a|b|d|f| 11
18

您可以看到它如何检查所有可能的路径,然后选择最高分:D

于 2019-11-25T15:06:56.610 回答
1

这是一种方法:

def maxscore(start, path, score):
    best_score = -1
    best_i = None
    best_path = None

    current_path = path + [start]
    for i in graph[start]:
        if not i in path:
            score_i, path_i = maxscore(i, current_path, score + graph[start][i])
            if score_i > best_score:
                best_score = score_i
                best_i = i
                best_path = path_i
    if best_i is None:
        return score, current_path
    else:
        return best_score, best_path

graph = {
    'a': {'b': 2, 'c': 4},
    'b': {'d': 5},
    'c': {'a': 1, 'e': 3},
    'd': {'f': 4},
    'e': {'b': 2, 'f': 3, 'g': 2},
    'f': {},
    'g': {}
}

print(maxscore('a', [], 0))

输出:

(18, ['a', 'c', 'e', 'b', 'd', 'f'])

笔记:

  • 在问题代码中,caminho 和 parentals 具有相同的功能。仅使用列表比使用字符串更容易使用。
  • 在 for 循环中,我们测试每条边。如果边缘的末端节点尚未在路径中,我们计算该边缘之后的最大分数。我们必须比较每一个可能的边缘,并保留一个得分最高的边缘。我们只能maxscore()在测试所有可能的边缘后返回。
  • 如果没有找到自由边,我们只返回当前分数和路径
  • 如果找到自由边,我们返回最佳边的分数和路径

PS:修改代码后,可以缩短一点。best_i并不是真正需要的,并且if best_i is None可以将测试替换为if best_path is None.

另外,如果需要字符串形式的路径,可以打印("|".join(best_path))。

于 2019-11-25T15:03:24.157 回答