具体问题描述如下
最大子矩阵和问题。给定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
分析:
该题是最大子段和问题的拓展,思路是可以将矩阵的多行压缩成成一行,然后对这一行用求最大子段和的方式求解,这里和求最大字段和稍微有一点区别,那就是我们不仅要记录下最大的字段和,还要记录下该最大字段和的起始位置和终止位置,这个两个位置就是题目上要求的列序号。而行序号的记录就是矩阵哪几行进行压缩得到的。
11 23 21 12
10 20 45 12
可以压缩为一行,同一列的进行相加,即
21 43 66 24
#include<iostream>
using namespace std;
#define MAX 101
int colbegin1,colend1,colbegin,colend,rowbegin,rowend;
//对求最大子段和的方法稍作改进,记录下最大字段的起始位置和终止位置
int Max(int a[],int n){
int max=0,temp=a[1],begin=1,end=1;
for(int i=2;i<=n;i++){
if(temp>0){
temp+=a[i];
end=i;//刷新终止位置
}
else{
temp=a[i];
begin=end=i;//重置起始位置和终止位置
}
if(temp>max){//记录下最后的结果,也就是最大值,列序号
max=temp;
colbegin1=begin;
colend1=end;
}
}
return max;
}
int main(){
int n,m,num[MAX][MAX],t[MAX];
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>num[i][j];
int sum,max=0;
for(int begin=1;begin<=n;begin++){
for(int k=1;k<=m;k++)
t[k]=0;//重置为0,这一步非常关键
for(int end=begin;end<=n;end++){
for(int k=1;k<=m;k++)
t[k]+=num[end][k];//从开始行到结束行进行压缩,压缩成一行
sum=Max(t,m);//求出这一行数据的最大子段和
if(sum>max){//刷新所要求的结果
max=sum;
rowbegin=begin;
rowend=end;
colbegin=colbegin1;
colend=colend1;
}
}
}
printf("%d\n",max);
printf("%d %d %d %d\n",rowbegin,rowend,colbegin,colend);
return 0;
}
如果觉得有帮助的话,记得点赞或者收藏支持一下嗷 ( :