题目描述:
给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。
其中,A的子矩阵指在A中行和列均连续的一块。
样例说明
取最后一列,和为10。
输入:
输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
接下来n行,每行m个整数,表示矩阵A。
数据规模和约定
对于100%的数据,1< =n, m< =500,A中每个元素的绝对值不超过5000。
输出:
输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
样例输入:
3 3
-1 -4 3
3 4 -1
-5 -2 8
样例输出:
10
**注意:**当出现矩阵元素全为负数时会出错,s=0,会将s赋给max,故得出的结果为0
并且这种方法不可取,不能仅根据某一列的和为负就将其丢弃,因为有可能出现这种情况:
不能因为第三列的和为负就将其丢弃,令s=0
而应继续往后加,最大应为3+4-2+10而不是丢弃-2后令s=0得到答案10
错误代码:
#include <bits/stdc++.h>
#define MAX 501
using namespace std;
int main()
{
int a[MAX][MAX]={0};
int sum[MAX][MAX]={0}; //sum[i][j]保存数组中第j列第一个到第i个元素的和
int n,m;
int i,j,c;
long long max=0,temp,s=0;
cin>>n>>m;
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
cin>>a[i][j];
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
sum[i][j]=sum[i-1][j]+a[i][j];
max=a[1][1];
for(i=1;i<=n;++i)
for(j=i;j<=n;++j)
{
s=0; //当为最后一列时不能再往后加了,要令s为零
for(c=1;c<=m;++c)
{
temp=sum[j][c]-sum[i-1][c];
if(temp>=0) //判断条件必须为>=,有可能出现这种情况:
{ s+=temp; //第一列和>0,第二列和=0,第三列和>0
if(s>max)
max=s; //有可能矩阵全部元素都大于0
}
else
{
if(s>max)
max=s;
s=0;
}
/*s+=sum[j][c]-sum[i-1][c];
if(s>max)
max=s;
if(s<0)
s=0;*/
}
}
cout<<max<<endl;
}
正确代码:
#include <bits/stdc++.h>
#define MAX 501
using namespace std;
int main()
{
int a[MAX][MAX]={0};
int sum[MAX][MAX]={0}; //sum[i][j]保存数组中第j列第一个到第i个元素的和
int n,m;
int i,j,c;
long long max=0,temp,s=0;
cin>>n>>m;
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
cin>>a[i][j];
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
sum[i][j]=sum[i-1][j]+a[i][j];
max=a[1][1];
for(i=1;i<=n;++i)
for(j=i;j<=n;++j)
{
s=0; //当为最后一列时不能再往后加了,要令s为零
for(c=1;c<=m;++c)
{
s+=sum[j][c]-sum[i-1][c];
if(s>max)
max=s; //每次都对max进行更新
if(s<0) //当前面几列的和小于零时再加一列和得到的答案
s=0; //会比只取那一列的和所得到的答案小,即s+s1<s1
} //故需要更新,即s=0
}
cout<<max<<endl;
}
改进代码一边输入a[i][j]一边将得到的j列第一个到第i个元素的和保存再数组a中,即将本应保存在数组sum中的数保存在数组a中
#include <bits/stdc++.h>
#define MAX 501
using namespace std;
int main()
{
int a[MAX][MAX]={0};
int n,m;
int i,j,c;
long long max=0,temp,s=0;
cin>>n>>m;
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
{
cin>>a[i][j];
a[i][j]+=a[i-1][j];
}
max=a[1][1];
for(i=1;i<=n;++i)
for(j=i;j<=n;++j)
{
s=0; //当为最后一列时不能再往后加了,要令s为零
for(c=1;c<=m;++c)
{
s+=a[j][c]-a[i-1][c];
if(s>max)
max=s; //每次都对max进行更新
if(s<0) //当前面几列的和小于零时再加一列和得到的答案
s=0; //会比只取那一列的和所得到的答案小,即s+s1<s1
} //故需要更新,即s=0
}
cout<<max<<endl;
}