最大子矩阵和问题。给定m行n列的整数矩阵A,求矩阵A的一个子矩阵,使其元素之和最大。
输入格式:
第一行输入矩阵行数m和列数n(1≤m≤100,1≤n≤100),再依次输入m×n个整数。
输出格式:
输出第一行为最大子矩阵各元素之和,第二行为子矩阵在整个矩阵中行序号范围与列序号范围。
输入样例1:
5 6
60 3 -65 -92 32 -70
-41 14 -38 54 2 29
69 88 54 -77 -46 -49
97 -32 44 29 60 64
49 -48 -96 59 -52 25
输出样例1:
输出第一行321表示子矩阵各元素之和,输出第二行2 4 1 6表示子矩阵的行序号从2到4,列序号从1到6
321
2 4 1 6
Code:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <list>
#include <sstream>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+7;
using namespace std;
#define ARR_SIZE 10001
#define Num 500005
int main()
{
int row1,row2,col1,col2;
row1 = row2 = col1 = col2 = 0;
int arr[101][101];
int n,m;
int aaa,sumMax=-INF;
cin>>n>>m;
memset(arr,0,sizeof(arr));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>aaa;
arr[i][j]=arr[i][j-1]+aaa; //用第i行第j列元素表示第i行前j列元素之和,方便后面运算
}
for(int i=1;i<=m;i++) //此循环用于求出第k行 第i列到第j列 的子矩阵元素之和
for(int j=i;j<=m;j++)
{
int sum=0;
for(int k=1;k<=n;k++)
{
if(sum<0) { //sum等于0时,会发生拖累, 让sum等于0
sum=0;
}
sum+=arr[k][j]-arr[k][i-1];
if(sumMax<sum){
sumMax=sum;
row2 = k;
col1 = i;
col2 = j;
}
}
}
for(int i = 1; i <= row2; i++){ //想了很多办法都没有能够求出行起点row1 后来在同学点拨下暴力回溯,搞定
int sum = 0;
for(int j = i; j <= row2; j++){
sum += arr[j][col2] - arr[j][col1-1];
}
if( sum == sumMax){
row1 = i;
break;
}
}
cout<<sumMax;
cout<<endl<<row1<<" "<<row2<<" "<<col1<<" "<<col2;
return 0;
}