最大化表的总和,其中每个数字必须来自唯一的行和列

时间:2011-08-02 21:18:19

标签: algorithm combinatorics

假设我们有一个这样的数字表(我们可以假设它是一个方形表):

20  2   1   3   4
5   1   14  8   9
15  12  17  17  11
16  1   1   15  18
20  13  15  5   11

您的工作是计算n个数字的最大总和,其中n是表格中的行数或列数。捕获量每个数字必须来自唯一的行和列。

例如,选择(0,0),(1,1),(2,2),(3,3)和(4,4)的数字是可以接受的,但是(0,0), (0,1),(2,2),(3,3)和(4,4)不是因为前两个数字是从同一行拉出的。

这个问题的我(可笑的)解决方案是遍历行和列的所有可能的排列。这适用于小网格,但当然,随着n变大,它会非常慢。它有O(n!)时间复杂度,如果我没有弄错的话(下面的Python代码示例)。

我真的认为这可以在更好的时间内解决,但我没有想出任何足够聪明的东西。

所以我的问题是,应该使用什么算法来解决这个问题?

如果有帮助,这个问题似乎类似于 knapsack problem

import itertools
import re

grid = """20    2   1   3   4
5   1   14  8   9
15  12  17  17  11
16  1   1   15  18
20  13  15  5   11"""
grid = [[int(x) for x in re.split("\s+", line)] for line in grid.split("\n")]

possible_column_indexes = itertools.permutations(range(len(grid)))
max_sum = 0
max_positions = []
for column_indexes in possible_column_indexes:
    current_sum = 0
    current_positions = []
    for row, col in enumerate(column_indexes):
        current_sum += grid[row][col]
        current_positions.append("(%d, %d)" % (row, col))
    if current_sum > max_sum:
        max_sum = current_sum
        max_positions = current_positions

print "Max sum is", max_sum
for position in max_positions:
    print position

2 个答案:

答案 0 :(得分:9)

这是最大成本的二分匹配问题。解决它的经典方法是使用Hungarian algorithm

基本上你有一个二分图:左边是行,右边是列。从行i到列j的每条边都有matrix[i, j]的费用。找到最大化成本的匹配。

答案 1 :(得分:0)

对于初学者,您可以使用动态编程。

在你直截了当的方法中,你做的次数完全相同。

例如,在某些时候,您回答了这个问题:“对于已经采用行1和行2的最后三列,如何最大化总和?”您计算此问题的答案两次,一次是从第1列中选择第1行,从第2列中选择第2行,在您选择第2行时反之亦然。

所以不要这样做。 缓存答案 - 并缓存所有类似问题的所有类似答案 - 并重复使用它们。

我现在没时间分析这种方法的运行时间。我认为是O(2 ^ n)或左右。更晚些时候也许......