题目描述
给定一个 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
思路:看见这个题,直接想到了二维前缀和,然后就超时了。。。然后用到了一维前缀和+双向指针。
,感觉前几个题都在模拟的路上。
二维前缀和超时代码:
import java.util.Scanner;
public class Main {
static int N = 200005;
static int[]a = new int[N];
static int[]b = new int[N];
public static void main(String[] args) {
new Main().solve();
}
void solve() {
int mod =1000000007;
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int k = sc.nextInt();
int arr[][] = new int[n+1][m+1];
int sum[][] = new int[n+1][m+1];
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
arr[i][j] = sc.nextInt();
sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+arr[i][j];
}
}
// for(int i=1;i<=n;i++) {
// for(int j=1;j<=m;j++) {
// System.out.print(sum[i][j]+" ");
// }
// System.out.println();
// }
long t = 0;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
for(int ii=i;ii<=n;ii++) {
for(int jj=j;jj<=m;jj++) {
if((sum[ii][jj]-sum[i-1][jj]-sum[ii][j-1]+sum[i-1][j-1])<=k) {
t++;
}else {
break;
}
}
}
}
}
System.out.println(t);
sc.close();
}
}
AC代码:
import java.util.Scanner;
public class Main {
static int N = 200005;
static int[]a = new int[N];
static int[]b = new int[N];
public static void main(String[] args) {
new Main().solve();
}
void solve() {
int mod =1000000007;
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int k = sc.nextInt();
int arr[][] = new int[n+1][m+1];
int sum[][] = new int[n+1][m+1];
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
arr[i][j] = sc.nextInt();
sum[i][j] += sum[i-1][j]+arr[i][j];
}
}
// for(int i=1;i<=n;i++) {
// for(int j=1;j<=m;j++) {
// System.out.print(sum[i][j]+" ");
// }
// System.out.println();
// }
long t = 0;
for(int i=1;i<=n;i++) {
for(int j=i;j<=n;j++) {
int res=0;
for(int l=1,r=1;r<=m;r++) {
res += sum[j][r]-sum[i-1][r];
while(res>k) {
res-=sum[j][l]-sum[i-1][l];
l++;
}
t+=r-l+1;
}
}
}
System.out.println(t);
sc.close();
}
}