(自用笔记,有错误请见谅)
原理
什么是二维前缀和:二维前缀和详解_Xiao J.的博客-CSDN博客_二维前缀
常与动态规划算法DP、容斥原理结合使用:动态规划算法(DP)_那什的博客-CSDN博客_dp算法g
算法存在问题:时间复杂度高,适用于数据量小的题目
公式
- 计算二维前缀和(从 s [1][1] 到 s [ i ] [ j ]形成的矩形的区域和):
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + x;
- 计算子矩阵和(从 s [ i1 ][ j1 ] 到 s [ i2 ][ j2 ]形成的矩形的区域和):
x = s[i2][j2] - s[i1-1][j2] - s[i2][j1-1] + s[i1-1][j1-1];
例题
输入:
3 2
4 0
-10 8
-2 -2
输出:4
思路
- 构建二维前缀海拔和
- 计算子矩阵和(海拔总和>0则平均海拔>0)
代码
参考:最大面积子矩阵(二维前缀和)_c_uizrp_dzjopkl的博客-CSDN博客
#include <bits/stdc++.h>
using namespace std;
long long s[201][201];
int n,m;
long long ans;
int main()
{
cin>>n>>m; //n行,m个数
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
int x;
cin>>x,
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + x; //计算前缀海拔和
}
long long i1,i2,j1,j2;
for (i1 = 1; i1 <= n; i1++)
for (j1 = 1; j1 <= m; j1++)
for (i2 = i1; i2 <= n; i2++)
for (j2 = j1; j2 <= m; j2++)
{
long long x = s[i2][j2] - s[i1-1][j2] - s[i2][j1-1] + s[i1-1][j1-1]; //计算一个面积的平均海拔
if (x > 0) ans = max(ans,(i2-i1+1) * (j2-j1+1)); //判断是否要更新面积
}
cout<<ans;
return 0;
}