【问题标题】:Maximize sum of table where each number must come from unique row and column最大化表的总和,其中每个数字必须来自唯一的行和列
【发布时间】:2011-10-18 14:59:47
【问题描述】:

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

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

【问题讨论】:

  • 出于好奇,您是从哪里遇到这个问题的?
  • 它在 codeeval.com 上遇到了挑战。不过我不会说是哪个!

标签: algorithm combinatorics


【解决方案1】:

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

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

【讨论】:

【解决方案2】:

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

在您的直接方法中,您正在多次执行完全相同的计算。

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

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

我现在没有时间分析这种方法的运行时间。我认为它是 O(2^n) 左右。以后可能会更...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-24
    • 2017-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 2017-01-04
    相关资源
    最近更新 更多