动态编程:在具有最大总和的网格中查找矩形

Mat*_*lda 1 algorithm dynamic-programming maximize

我遇到了以下动态编程问题.

你有一个整数网格(所以包括负数).找到具有最大数字总和的矩形.

知道如何为整个矩阵做到这一点吗?

我为一个阵列解决了这个问题,所以我几乎遵循了增长最快的子程序,但仅限于连续数字.

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
Run Code Online (Sandbox Code Playgroud)

所以我的想法是,

  1. 找到矩阵中每个方格的总和(仅1x1个方块)
  2. 为可能的答案保存最大值
  3. 从最小可能的矩形开始运行相同的事物并计算所有矩形,直到找到最大值.哪个是DB部分.

有任何想法吗?或者如果你们不知道确切的解决方案,我应该看哪种DP类型的算法?

Pet*_*hev 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;
   } 
Run Code Online (Sandbox Code Playgroud)

sumBetween是一个函数,返回两列之间特定行上的数字之和.它可以使用预先计算的总和在恒定时间内实现.

int sumBetween(int leftCol, int rightCol, int row)
{
    return sum[row][rightCol] - sum[row][leftCol - 1];
}
Run Code Online (Sandbox Code Playgroud)

要计算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];
Run Code Online (Sandbox Code Playgroud)