题目描述
给定一个 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
说明/提示
【样例说明】
满足条件的子矩阵一共有 19,包含:
大小为 1×1 的有 10 个。
大小为 1×2 的有 3 个。 大小为 1×3 的有 2 个。
大小为 1×4 的有 1 个。
大小为 2×1 的有 3 个。
【评测用例规模与约定】
对于 30% 的数据, N,M≤20.
对于 70% 的数据, N,M≤100.
对于 100% 的数据, 1≤N,M≤500,0≤Aij≤1000,1≤K≤2.5×108.
蓝桥杯 2022 省赛 B 组 F 题。
P8783 [蓝桥杯 2022 省 B] 统计子矩阵 - 洛谷
这题我运用二维前缀和公式和然后利用计算子矩阵和公式解决这题,但只得了80分
使用二维前缀和,用 sum[i][j] 表示矩阵中 x∈[1,i],y∈[1,j] 的所有元素之和。其递推式为 sum[i][j]=sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1]+arr[i][j]
所以矩阵该矩阵的元素之和就可以用 sum[c][d] - sum[c][b - 1] - sum[a - 1][d] + sum[a - 1][b - 1]
以下是我c语言提交的代码仅供参考:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<limits.h>
#include<stdlib.h>
#include<math.h>
#include <stdbool.h>
int sum[501][501] = { 0 };
//计算二维矩阵中从左上角坐标 (a,b) 到右下角坐标 (c,d) 的子矩阵的和。
int sums(int a, int b, int c, int d)
{
return sum[c][d] - sum[c][b - 1] - sum[a - 1][d] + sum[a - 1][b - 1];
}
int main()
{
int n, m, k = 0; int count = 0;
int arr[501][501] = { 0 };
scanf("%d %d %d", &n, &m,&k);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%d", &arr[i][j]);
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
//二维前缀和计算
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++)
{
for (int x = i; x <= n; x++)
{
for (int y = j; y <= m; y++)
{
if (sums(i, j, x, y) <= k)
{
count++;
}
}
}
}
}
printf("%d\n", count);
return 0;
}