📜  门|门CS 2011 |第 45 题(1)

📅  最后修改于: 2023-12-03 15:28:48.949000             🧑  作者: Mango

题目介绍:门 | 门CS 2011 | 第 45 题

这是一道计算题。题目要求我们求出给定的矩阵中,每个位置上的数与它周围4个位置的数之和的最大值。矩阵的大小是 $n$ 行 $m$ 列。

解题思路

首先,我们需要遍历整个矩阵,对于每一个位置,计算周围4个位置的和。由于求和操作是一个常数时间操作,所以整个遍历过程的时间复杂度是 $O(nm)$。

但是,这个算法是比较慢的。因为它存在重复计算的情况。对于任意一个位置 $(i,j)$,它的左上、右上、左下、右下四个位置的和已经被计算过了。我们完全可以用这个已经计算好的值,来避免对这些位置重复计算。

于是,我们可以在第一次遍历的时候,把已经计算过的位置的和(也就是左上、右上、左下、右下)保存下来。这样的话,第二次遍历时,我们就可以直接使用已经计算好的值,来避免重复计算,从而达到优化的目的。

代码实现

下面是伪代码的实现,使用了两层循环。第一层循环枚举行,第二层循环枚举列。在循环中,我们用一个二维数组 $sum$ 来记录已经计算过的位置的和。如果我们要计算 $(i,j)$ 这个位置的和,那么我们只需要记住左上、右上、左下、右下四个位置的和即可。

sum = new int[n][m];
for(int i=0; i<n; i++) {
  for(int j=0; j<m; j++) {
    if(i > 0) { // 上面一行
      sum[i][j] += sum[i-1][j];
    }
    if(j > 0) { // 左边一列
      sum[i][j] += sum[i][j-1];
    }
    if(i > 0 && j > 0) { // 左上角
      sum[i][j] -= sum[i-1][j-1];
    }
    if(i > 0 && j < m-1) { // 右上角
      sum[i][j] += sum[i-1][j+1];
    }
    // 计算 (i,j) 位置的和
    int s = a[i][j];
    if(j > 0) { // 左边
      s += sum[i][j-1];
    }
    if(i > 0) { // 上面
      s += sum[i-1][j];
    }
    if(i < n-1) { // 下面
      s += sum[i+1][j];
    }
    if(j < m-1) { // 右边
      s += sum[i][j+1];
    }
    // 更新最大值
    ans = max(ans, s);
  }
}