题目应该很容易看懂,是为了求一个矩阵之内最大的一个子矩阵的和。
子矩阵的和表示的是该矩阵内所有元素的和。
方法引入:
首先当然十分容易的可以想到一维求子段的和。
假设数组为a[110];
int sum = 0, MAX = 0,n; for (int i = 0; i < n; i++) { if (sum < 0) sum = 0; sum += a[i]; if (sum>MAX) MAX = sum; }
其中a[i]表示的是你所要积的范围大小,因为是一维,所以我们要积的是每一个元素。并且采取的是横向遍历即可。
由此迁移到二维。
二维采取的也是相同的方法,依然要找出a[i],但是循环多了一些。
思路我稍微描述一下(估计会看不懂):对于二维,做过覆盖面积最大的同学都知道,我们采取的是先处理横向,再处理竖向。
我们此处采取的方法就是固定横向,这边横向我们叫之为子矩阵的宽,我们去伸缩子矩阵的长,从而得到在此宽下,最大的子矩阵和。
然后在增大宽,并且移动宽的位置去重复以上的步骤,最终得到最大的子矩阵的和。(不知道听得懂不)
看下代码:
for (int i = 1; i <= n;i++)//这个循环控制宽的起点,1,2,3,,, for (int j =i; j <= n; j++)//这个循环去控制宽的长度,1,2,3,,, { sum = 0; for (int k = 1; k <= n; k++)//再此基础上k来控制长,相当于将一维的横向处理放到行上来。想一下,是不是如此? { if (sum < 0) sum = 0; sum += map[k][j] - map[k][i - 1];//map[k][j]-map[k][i-1]这边处理就可以得到宽,并且起点是从i开始的一条j-i+1长度的宽。 if (sum>MAX) MAX = sum; } }
看一下完整代码:
#include<iostream> using namespace std; /* 通过暴力的方法。 计算子矩阵和的方法,将二维转化成一维。 如何得到第k行,i-j的和。然后累加按一维的方法求出最大值。 */ int map[110][110]; int main() { int n; while (cin >> n) { for (int i = 1; i <= n; i++) { map[i][0] = 0; for (int j = 1; j <= n; j++) { scanf("%d", &map[i][j]); map[i][j] += map[i][j - 1]; } } int sum = 0; int MAX = 0; for (int i = 1; i <= n;i++)//这个循环控制宽的起点,1,2,3,,, for (int j =i; j <= n; j++)//这个循环去控制宽的长度,1,2,3,,, { sum = 0; for (int k = 1; k <= n; k++)//再此基础上k来控制长,相当于将一维的横向处理放到行上来。想一下,是不是如此? { if (sum < 0) sum = 0; sum += map[k][j] - map[k][i - 1];//map[k][j]-map[k][i-1]这边处理就可以得到宽,并且起点是从i开始的一条j-i+1长度的宽。 if (sum>MAX) MAX = sum; } } cout << MAX << endl; } }
时间: 2024-12-24 07:44:56