给定一个 N×M 的矩阵 A,请你统计有多少个子矩阵 (最小 1×1,最大 N×M) 满足子矩阵中所有数的和不超过给定的整数 K?
输入格式
第一行包含三个整数 N,M 和 K。
之后 NN 行每行包含 M 个整数,代表矩阵 A。
输出格式
一个整数代表答案。
数据范围
对于 30% 的数据,N,M≤20,
对于 0% 的数据,N,M≤100,
对于 100% 的数据,1≤N,M≤500;0≤Aij≤1000;1≤K≤250000000
输入样例:
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
输出样例:
19
样例解释
满足条件的子矩阵一共有 19,包含:
- 大小为 1×11×1 的有 10 个。
- 大小为 1×21×2 的有 3 个。
- 大小为 1×31×3 的有 2 个。
- 大小为 1×41×4 的有 1 个。
- 大小为 2×12×1 的有 3 个。
解题思路:优化为o(n^3)
先初始化每一列的前缀和,在依次枚举每一行。同时用双指针优化。
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 510;
int a[N][N],b[N][N];
int main()
{
int n,m,K;
scanf("%d%d%d",&n,&m,&K);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
b[i][j] = b[i-1][j]+a[i][j];
}
}
long long res=0;
for(int i=1;i<=n;i++)//上届
{
for(int j=i;j<=n;j++)//下届
{
for(int l=1,r=1,sum=0;r<=m;r++)
{
sum += b[j][r]-b[i-1][r];
while(sum > K)
{
sum -= b[j][l] - b[i-1][l];
l++;
}
res += r-l+1;//以l为左端点r为右端点
//表示l到r有几个子矩阵
//1 ... 5的子矩阵
//1 12 123 1234 12345
}
}
}
printf("%lld\n",res);
return 0;
}