感谢@ctq1999指出本题解代码不宜巨佬学习,所以萌新我修改了一波代码,变成了萌新版代码.
题目描述
给定一个包含整数的二维矩阵,子矩形是位于整个阵列内的任何大小为1 * 1或更大的连续子阵列。
矩形的总和是该矩形中所有元素的总和。
在这个问题中,具有最大和的子矩形被称为最大子矩形。
例如,下列数组:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩形为:
9 2
-4 1
-1 8
它拥有最大和15。
输入格式
输入中将包含一个$N^2$的整数数组。
第一行只输入一个整数N,表示方形二维数组的大小。
从第二行开始,输入由空格和换行符隔开的$N^2$个整数,它们即为二维数组中的$N^2$个元素,输入顺序从二维数组的第一行开始向下逐行输入,同一行数据从左向右逐个输入。
数组中的数字会保持在$[-127,127]$的范围内。
输出格式
输出一个整数,代表最大子矩形的总和。
数据范围
$1≤N≤100$
样例
输入样例:
4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1
8 0 -2
输出样例:
15
贪心+前缀和
解题思路:首先我们容易想到,可以枚举矩阵的左上角$(x_1,y_1)$和右下角$(x_2,y_2)$ ,然后通过二维前缀和算出矩阵和,这样就可以确定我们所需要的矩阵,但是时间复杂度是$O(n^4)$,这样的复杂度太大了,我们无法解决.所以我们可以换一种思想,贪心处理.问题是我们怎么贪心了, 大致可以这样大力贪心
首先我们自行模拟一遍矩阵,发现一个重要的性质就是,如果说当前的答案加上当前这一排让我们当前的ans值小于0的话,那么这一排包括这一排上面的数值,我们都可以不要了,因为如果我们选择了上面的矩阵,还不如不去选择这个矩阵.这一点比较难以理解,我们画一个图理解一下.
感谢@昂昂累世士大佬和一个月前私信告诉我的@wulai大佬指出,本题解有一个小Bug,初始化的ans最小值因为一个特别小的负数.
这里提供一组Hack数据,稍后应该会加入数据库吧.
输入
4
-3 -2 -7 -7 -9 -2 -6 -2
-4 -1 -4 -1 -1
-8 -4 -2
输出
-1
C++ 代码
//之前有大佬说,define不宜萌新学习,所以萌新我决定稍微修改了代码
#include <bits/stdc++.h>
using namespace std;
const int N=110;
int a[N][N],s[N][N],n,m,i,j,ans=-1e8,now_ans;
bool ok=false;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
if (a[i][j]>=0)
ok=true;
ans=max(ans,a[i][j]);
}
if (!ok)//注意特殊判定
{
cout<<ans;
return 0;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
s[i][j]=s[i-1][j]+a[i][j];
for(int l=1;l<=n;l++)
for(int r=l;r<=n;r++)
{
now_ans=0;
for(int l2=1;l2<=n;l2++)
{
now_ans+=s[r][l2]-s[l-1][l2];
if (now_ans<0)
now_ans=0;
if (now_ans>ans)
ans=now_ans;
}
}
cout<<ans;
return 0;
}
然而O(n^4)可以卡常过
大佬,交不过了
没必要特判的啊,只要把计算答案的两个判断交换一下(因为这种顺序可能有点问题,也能过的
特判加一个,也没有多大问题吧,这样是为了稳妥.QwQ
QAQ,好吧,大佬说的都对!
QwQ,①我不是大佬②您是大佬,顺序都可以这么巧妙的交换③这个特判不是个人习惯么?
cvc gugugu,可能是个人喜好问题吧,我不喜欢特判 cvc,而且我最篛了
QwQ您虚伪!
╭(╯^╰)╮您才fake
作者,看题解的都是萌新,你的代码里都是自己define的东西, 给萌新不少困难啊
稍等哈,我去修改成通俗易懂的代码.其实我也就一段时间用了define.98%的代码是没有用define.
萌新我已经修改.
其实我看过的题解你都这样诶QWQ~
谢谢作者!
不会吧,我记得这个#define用在for循环,只有那么四五次啊.
大佬,你这代码是不是没考虑全是负数的情况啊,可能需要小小的修改
考虑了,你看我的ans=0
如果都是负数,显然一个都不选是最优值.
不能一个都不选吧,题目说子矩阵是1*1或者更大的序列,求子矩阵最大和不可能一个不选的,比如说求数组的最大连续和,你不可能一个元素都不要,yxc视频里ans的初值也是很小的负数
是的,感谢@昂昂累世士,我的题解的确有一个小BUG.稍后这道题目应该会加入这组Hack数据.
已经修改.蟹蟹.