21xrx.com
2024-12-23 00:34:15 Monday
登录
文章检索 我的文章 写文章
C++二维数组求子矩阵和左上角右下角的所有路线
2023-06-26 17:45:57 深夜i     --     --
C++ 二维数组 子矩阵和 左上角 右下角 路线

近年来,C++作为一门非常流行的编程语言,应用于各种领域。在计算机科学领域中,二维数组是一种常见的数据结构。而对于二维数组中的子矩阵,求其和以及左上角到右下角的所有路线也是很常见的问题。

对于求子矩阵的和,可以采用动态规划的思想。假设原矩阵为M,新建一个矩阵S,其中S[i][j]表示以M[0][0]为左上角,以M[i][j]为右下角的子矩阵的和。那么根据动态规划的思想,S[i][j] = S[i-1][j] + S[i][j-1] - S[i-1][j-1] + M[i][j]。即当前位置的累加和,等于上方、左侧、左上方的累加和之和再加上当前位置的值。

对于求左上角到右下角的所有路线,可以采用回溯算法。从左上角开始,依次遍历相邻的格子(即右、下方向),直到到达右下角。在这个过程中,记录每个遍历到的格子的坐标,就是左上角到右下角的所有路线。

以下是一个C++代码的示例,可以更好地说明这个过程:


#include <iostream>

#include <vector>

using namespace std;

// 动态规划求二维数组的子矩阵和

void subMatrixSum(vector<vector<int>>& m, vector<vector<int>>& s) {

  int row = m.size();

  int col = m[0].size();

  s[0][0] = m[0][0];

  for (int i=1; i<row; i++)

    s[i][0] = s[i-1][0] + m[i][0];  // 第一列

  for (int j=1; j<col; j++)

    s[0][j] = s[0][j-1] + m[0][j];  // 第一行

  for (int i=1; i<row; i++) {

    for (int j=1; j<col; j++) {

      s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + m[i][j];

    }

  }

}

// 回溯求左上角到右下角的所有路线

void getAllPath(vector<vector<int>>& m, int row, int col, vector<int>& path, vector<vector<int>>& res) {

  if (row == m.size()-1 && col == m[0].size()-1) {  // 到达右下角

    res.push_back(path);

    return;

  }

  if (row < m.size()-1) {  // 往下走

    path.push_back(m[row+1][col]);

    getAllPath(m, row+1, col, path, res);

    path.pop_back();

  }

  if (col < m[0].size()-1) { // 往右走

    path.push_back(m[row][col+1]);

    getAllPath(m, row, col+1, path, res);

    path.pop_back();

  }

}

int main() {

  vector<vector<int>> matrix = {{1,2,3},

                 {4,5,6},

                 {7,8,9}};

  vector<vector<int>> subSum(matrix.size(), vector<int>(matrix[0].size(), 0));

  subMatrixSum(matrix, subSum);

  for (int i=0; i<subSum.size(); i++) {

    for (int j=0; j<subSum[0].size(); j++) {

      cout << subSum[i][j] << " ";

    }

    cout << endl;

  }

  vector<int> path = {1};  // 左上角

  vector<vector<int>> allPath;

  getAllPath(matrix, 0, 0, path, allPath);

  for (int i=0; i<allPath.size(); i++) {

    for (int j=0; j<allPath[i].size(); j++) {

      cout << allPath[i][j] << " ";

    }

    cout << endl;

  }

  return 0;

}

在这个示例代码中,使用了vector >存储二维数组。其中,subSum表示的是原矩阵的子矩阵和。allPath则是记录所有左上角到右下角的路线。可以看到,动态规划和回溯算法都有非常好的效果,分别解决了对应的问题。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复