最大子矩阵和
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵。 比如,如下4 * 4的矩阵 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 的最大子矩阵是 9 2 -4 1 -1 8 这个子矩阵的大小是15。
解析:这道题目参考此视频的思路,这里用了三层循环,用辅助矩阵a来记录这一行中,从1-i所有位置的和,计算i~j
列的和只需要用a[j] - a[i - 1],减少计算i~j
列的和这一层循环。
实际是使用了枚举+贪心的思路,先用两层for循环遍历所有可能形成矩形的的宽度,第三层循环遍历可能形成的矩形的高度,这里由于形成矩形的边一定是连续的,如果遇到之前的行和值res加起来小于0,则不应该从该行开始,将res置0,往后遍历,又比暴力解法节省一层循环,三层循环即可计算出所有可能的矩阵和结果,用打擂法将最大的结果保存输出即可。
# python
n = int(input())
matrix = [[0] * (n) for _ in range(n)] # 由于矩形可以由所有元素组成,此时宽的开始索引为i=1,j=n,一行上的和值为a[j]-a[0]
a = [[0] * (n + 1) for _ in range(n + 1)] # 所以a要留出第0列
max = -float('inf')
pos = [0] * 4
for i in range(1, n + 1):
matrix[i - 1] = [int(n) for n in input().split(" ")]
for j in range(1, n + 1):
a[i][j] = a[i][j - 1] + matrix[i - 1][j - 1]
for i in range(0, n): # 列的左边界
for j in range(i + 1, n + 1): # 列的右边界
res = 0 # 限定一种宽,计算以该宽度形成的矩形中的最大结果,但改变宽度,res置零重新计算另一种情况
h = 0 # 计算高度
for k in range(1, n + 1): # 遍历矩形的高度
res += a[k][j] - a[k][i] # 用大矩形面积减去前面矩形的面积即是i-j围成的面积
if res > max: # 及时更新结果
h += 1
max = res
pos = [k - h, i + 1, k, j] # 保存矩形的起始及终点坐标
if res < 0: # res小于0,高的开始索引从下一行开始
res = 0
h = 0
print(max)
print(pos)