我遇到了以下动态编程问题。
你有一个整数网格(所以包括负数)。找到具有最大数字总和的矩形。
知道如何为整个矩阵做到这一点吗?
我为一个阵列解决了这个问题,所以我几乎遵循了增长最快的子程序,但仅限于连续数字。
def array_largest_block(sequence)
len = sequence.size
parents = [nil]*len
my_largest = sequence
largest = sequence.max
for index in (1...len)
if my_largest[index] < my_largest[index] + my_largest[index - 1]
my_largest[index] = my_largest[index] + my_largest[index - 1]
parents[index] = index - 1
largest = [largest, my_largest[index]].max
end
end
end_index_of_largest_block = my_largest.find_index(largest)
i = end_index_of_largest_block
res = []
res << sequence[i]
while !parents[i].nil?
i = parents[i]
res << sequence[i]
end
return {l_sum: largest, start: i, end: end_index_of_largest_block}
end
所以我的想法是,
有什么想法吗?或者,如果你们不知道确切的解决方案,我应该看哪种DP类型算法?
答案 0 :(得分:5)
这可以在O(N^3)
中完成,其中N
是矩阵的大小。
您基本上选择矩形的左右列,然后以线性时间扫描行(使用预先计算的总和)。
int totalBestSum = -10000000;
for (int leftCol = 1; leftCol <= N; leftCol++)
for (int rightCol = leftCol; rightCol <= N; rightCol++)
{
int curSum = 0, curBestSum = -10000000;
for (int row = 1; row <= N; row++) {
int rowSum = sumBetween(leftCol, rightCol, row);
curSum += rowSum;
if (curSum > curBestSum) curBestSum = curSum;
if (curSum < 0) curSum = 0;
}
if (curBestSum > totalBestSum) totalBestSum = curBestSum;
}
sumBetween
是一个函数,返回两列之间特定行上的数字之和。它可以使用预先计算的总和在恒定时间内实现。
int sumBetween(int leftCol, int rightCol, int row)
{
return sum[row][rightCol] - sum[row][leftCol - 1];
}
计算sum
数组:
for (int row = 1; row <= N; row++)
for (int col = 1; col <= N; col++)
sum[row][col] = sum[row][col - 1] + matrix[row][col];
答案 1 :(得分:1)