该题及其解题思路来源于王道机试指南,侵删
-
问题描述:
求二维矩阵最大子矩阵的和 -
解题思路:
假设二维数组的最大子矩阵是从 i 行到 j 行,那么会与两种情况:
(1)当i = j 时,变成了求 i 行最大子序列和的问题。
(2)当 i ≠ j 时,利用辅助矩阵 total[ ][ ],辅助矩阵保存原矩阵从上到下加起来的累加和。故total的 j 行 i 行相减即为一个一维的最大子序列,接下来就可以利用上篇博文求最大子序列的和方法求解。
附代码
#include<iostream>
#include<cstdio>
#include<stdlib.h>
using namespace std;
int maxsubsequence(int n,int* arr)
{
int* dp = (int*)malloc(sizeof(int)*n);
dp[0] = arr[0];
int maxmum = dp[0];
for(int i = 1;i<n;i++)
{
dp[i] = max(arr[i],dp[i-1]+arr[i]);
if(maxmum < dp[i])
maxmum = dp[i];
}
free(dp);
return maxmum;
}
int maxsubmatrix(int n,int** matrix,int** total)
{
int* arr = (int*)malloc(sizeof(int)*n);
int maxsum = 0;
for(int i = 0;i<n;i++)//子矩阵首行
{
for(int j = i;j<n;j++)//子矩阵尾行
{
for(int k = 0;k<n;k++)
{
if(i == 0){
arr[k] = total[j][k];
}
else
arr[k] = total[j][k] - total[i-1][k];
}
int current = maxsubsequence(n,arr);
maxsum = max(maxsum,current);
}
}
free(arr);
return maxsum;
}
int main()
{
int n;
while(scanf("%d",&n)!= EOF)
{
int **matrix = (int**)malloc(sizeof(int*)*n);//存放输入的矩阵
int **total = (int**)malloc(sizeof(int*)*n);//辅助矩阵,total[i][j]表示matrix矩阵0-j列第i行值的和,就是第j列的列和
for(int i = 0;i<n;i++)
{
matrix[i] = (int*)malloc(sizeof(int)*n);
for(int j = 0;j<n;j++)
scanf("%d",&matrix[i][j]);
}
for(int i = 0;i<n;i++)//初始化辅助函数
{
total[i] = (int*)malloc(sizeof(int)*n);
for(int j = 0;j<n;j++)
{
if(i == 0)
total[i][j] = matrix[i][j];
else
total[i][j] = matrix[i][j] + total[i-1][j];
}
}
int answer = maxsubmatrix(n,matrix,total);
printf("%d\n",answer);
free(matrix);
free(total);
}
return 0;
}