题目
给定一个 N×M 的矩阵 A,请你统计有多少个子矩阵 (最小 1×1,最大 N×M) 满足子矩阵中所有数的和不超过给定的整数 K?
输入
第一行包含三个整数 N,M 和 K。
之后 N 行每行包含 M 个整数,代表矩阵 A。
输出
一个整数代表答案。
样例
输入样例:
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
输出样例:
19
暴力做法(会超时)
#include<iostream>
using namespace std;
const int N=510;
int q[N][N],s[N][N];
int n,m,k;
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&q[i][j]);
s[i][j] = s[i-1][j]+s[i][j-1]-s[i-1][j-1]+q[i][j];
}
}
int res= 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int a=i;a<=n;a++){
for(int b=j;b<=m;b++){
int sum = s[a][b]-s[i-1][b]-s[a][j-1]+s[i-1][j-1];
if(sum<=k) res++;
}
}
}
}
printf("%d",res);
}
优化成一维
#include<iostream>
using namespace std;
const int N=510;
int s[N][N];
int n,m,k;
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&s[i][j]);
s[i][j] += s[i-1][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 += s[j][r]-s[i-1][r];
while(sum>k){
sum -= s[j][l]-s[i-1][l];
l++;
}
res += r-l+1;
}
}
}
printf("%lld",res);
}