返回

方格取数:巧用思维,高效解答

闲谈

问题概述

方格取数问题的题面如下:

设有N×N的方格图(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):

0 1 0 2 0
3 0 0 0 0
0 0 4 0 5
0 0 0 0 6
0 7 0 8 9

某人从图的左上角的AA点出发,可以向下行走,也可以向右走,每次只能走一步。当他走到某个方格时,他可以收集该方格中的正整数。他的目标是收集尽可能多的正整数,并最终到达右下角的BB点。

解决思路

方格取数问题可以用动态规划算法来解决。动态规划算法是一种解决最优化问题的技术,它将问题分解成若干个子问题,然后逐步求解这些子问题,最终得到整个问题的最优解。

在方格取数问题中,我们可以将问题分解成若干个子问题,每个子问题都是从图中的某个方格出发,到达右下角的BB点。我们可以用一个二维数组dp来存储每个子问题的最优解,其中dp[i][j]表示从方格(i, j)出发,到达右下角的BB点的最优解。

为了计算dp[i][j],我们可以考虑从方格(i, j)出发,向下或向右走一步,然后到达方格(i+1, j)或(i, j+1)。我们选择走一步后获得的正整数较大的那个方向,并将其作为dp[i][j]的值。

如果方格(i, j)中没有正整数,那么dp[i][j]的值就等于0。

当我们计算完所有的dp[i][j]值之后,dp[1][1]的值就是从左上角的AA点出发,到达右下角的BB点的最优解。

代码实现

以下是用C++实现的方格取数问题的代码:

#include <iostream>
#include <vector>

using namespace std;

int main() {
  int n;
  cin >> n;

  // 创建一个二维数组dp来存储每个子问题的最优解
  vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));

  // 从第一行开始,计算每一行的dp值
  for (int i = 1; i <= n; i++) {
    // 从第一列开始,计算每一列的dp值
    for (int j = 1; j <= n; j++) {
      // 读取当前方格中的正整数
      int num;
      cin >> num;

      // 计算从当前方格出发,向下或向右走一步后获得的正整数较大的那个方向
      int next = max(dp[i - 1][j], dp[i][j - 1]) + num;

      // 将较大的正整数作为当前方格的dp值
      dp[i][j] = next;
    }
  }

  // 输出从左上角的AA点出发,到达右下角的BB点的最优解
  cout << dp[n][n] << endl;

  return 0;
}

总结

方格取数问题是一个经典的动态规划问题,它要求我们从一个方格图的左上角出发,向下或向右移动,最终到达右下角,并沿途收集方格中的正整数。本文详细介绍了方格取数问题的解决思路和代码实现,帮助读者理解并掌握这一重要算法。