12.3最大子矩阵(北京大学复试题)

王道课本P227 例12.3

本题是最大连续子序列的变种问题,需要将矩阵压缩成一维问题,当作最大连续子序列和问题来处理,再利用动态规划法问题求解dp[n]

CASE 1: i == j (矩阵matrix的i行和j行为同一行时,就是最大连续子序列问题)
CASE 2: i != j 时,可以将矩阵i行到j行压缩成一行,然后转换成一维的最大连续子序列问题来处理
#include<iostream>
#include <vector>
using namespace std;
//例12.3最大子矩阵

const int inf = INT_MAX;
int main() {
		int n;
		cin >> n;
		vector<int> dp(n);
		vector<vector<int>> matrix(n, vector<int>(n));

		for (int i = 0; i < n; i++) { //初始化矩阵数据
			for (int j = 0; j < n; j++) {
				cin >> matrix[i][j];
			}
		}
		if (n == 1) {
			cout << matrix[0][0] << endl;
			return 0;
		}
		int ans = -inf;
		for (int i = 0; i < n; i++) {
			for (int j = i; j < n; j++) {  //i要大于j,不然倒着算可能会算错
				vector<int> nums(n,0); //辅助一维数组
				if (i == j) {
					//case 1,i==j行转化成一维矩阵求最大序列和
					nums = matrix[i];	
				}
				else {
					//case 2: i!=j行, 将i行到j行压缩成为一个新的一行,再利用一维矩阵最大连续子序列和来求解该问题
					//步骤一:压缩二维矩阵为一维矩阵
					for (int m = 0; m < n; m++) {
						for (int h = i; h <= j; h++) {
							nums[m] += matrix[h][m];
						}
					}
				}
				//转换成一维矩阵求最大序列和				
				for (int k = 0; k < n; k++) {
					if (k == 0) {   //这样的写法可以避免dp[0]是最大值时候,忘记把dp[0]放进来比较一下
						dp[0] = nums[0];
					}
					else {
						dp[k] = max(nums[k], dp[k - 1] + nums[k]);
					}				
					ans = max(ans, dp[k]);
				}
			}
		}
		cout << ans << endl;
		return 0;
}