不求点赞,只求耐心看完,指出您的疑惑和写的不好的地方,谢谢您。本人会及时更正感谢。希望看完后能帮助您理解算法的本质
目录
- [蓝桥杯 2022 省 B] 统计子矩阵
- 题目描述
- 输入格式
- 输出格式
- 样例 #1
- 样例输入 #1
- 样例输出 #1
- 提示
- 一、本题考察算法:四重循环二维前缀和 -- 三重循环二维前缀和
- 思路:超时
- 代码:
- 二、三重循环的二维前缀和:
- 思路:
- 代码:
给定一个 N × M N \times M N×M 的矩阵 A A A,请你统计有多少个子矩阵 (最小 1 × 1 1 \times 1 1×1, 最大 N × M ) N \times M) N×M) 满足子矩阵中所有数的和不超过给定的整数 K K K。
第一行包含三个整数 N , M N, M N,M 和 K K K。
之后 N N N 行每行包含 M M M 个整数, 代表矩阵 A A A。
一个整数代表答案。
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
19
【样例说明】
满足条件的子矩阵一共有 19 19 19,包含:
大小为 1 × 1 1 \times 1 1×1 的有 10 10 10 个。
大小为 1 × 2 1 \times 2 1×2 的有 3 3 3 个。 大小为 1 × 3 1 \times 3 1×3 的有 2 2 2 个。
大小为 1 × 4 1 \times 4 1×4 的有 1 1 1 个。
大小为 2 × 1 2 \times 1 2×1 的有 3 3 3 个。
【评测用例规模与约定】
对于 30 % 30 \% 30% 的数据, N , M ≤ 20 N, M \leq 20 N,M≤20.
对于 70 % 70 \% 70% 的数据, N , M ≤ 100 N, M \leq 100 N,M≤100.
对于 100 % 100 \% 100% 的数据, 1 ≤ N , M ≤ 500 , 0 ≤ A i j ≤ 1000 , 1 ≤ K ≤ 2.5 × 1 0 8 1 \leq N, M \leq 500,0 \leq A_{i j} \leq 1000,1 \leq K \leq 2.5\times10^8 1≤N,M≤500,0≤Aij≤1000,1≤K≤2.5×108.
蓝桥杯 2022 省赛 B 组 F 题。
#include
using namespace std;
typedef long long LL;
const int N = 5e2 + 10;
LL s[N][N]; //前缀和矩阵
int n, m, k;
int main()
{
cin >> n >> m >> k;
for (int i=1; i <= n; i++)
{
for (int j=1; j <= m; j ++)
{
cin >> s[i][j];
s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1];
}
}
int cnt=0;
for (int x1=1; x1 <= n; x1 ++)
{
for (int y1=1; y1 <= m; y1 ++)
{
for (int x2=x1; x2 <= n; x2 ++)
{
for (int y2=y1; y2 <= m; y2 ++)
{
int sum = s[x2][y2] - s[x2][y1-1] - s[x1-1][y2] + s[x1-1][y1-1];
if (sum <= k)
cnt ++;
}
}
}
}
cout << cnt << endl;
return 0;
}
#include
#include
#include
using namespace std;
typedef long long LL;
int n, m, k;
const int N = 5e2 + 10;
int s[N][N]; //前缀和矩阵!
int main()
{
cin >> n >> m >> k;
for (int i=1; i <= n; i ++)
for (int j=1; j <= m; j ++)
{
cin >> s[i][j];
s[i][j] += s[i-1][j];//求列方向上的和更为方便!先背过这个技巧吧,能够快速地枚举所有的子矩阵
}
LL 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;
}
}
}
cout << res << endl;
return 0;
}