1087 字
5 分钟
GESP 2025年C++四级编程题解析
2025/03/22
2024/09/30

202509-1 排兵布阵#

题目描述

作为将军,你自然需要合理地排兵布阵。地图可以视为 nnmm 列的网格,适合排兵的网格以 1 标注,不适合排兵的网格以 0 标注。现在你需要在地图上选择一个矩形区域排兵,这个矩形区域内不能包含不适合排兵的网格。请问可选择的矩形区域最多能包含多少网格?

输入格式

第一行,两个正整数 n,mn, m,分别表示地图网格的行数与列数。

接下来 nn 行,每行 mm 个整数 ai,1,ai,2,,ai,ma_{i,1}, a_{i,2}, \ldots, a_{i,m},表示各行中的网格是否适合排兵。

输出格式

一行,一个整数,表示适合排兵的矩形区域包含的最大网格数。

样例输入 1

4 3
0 1 1
1 0 1
0 1 1
1 1 1

样例输出 1

4

样例输入 2

3 5
1 0 1 0 1
0 1 0 1 0
0 1 1 1 0

样例输出 2

3

提示

对于所有测试点,保证 1n,m121 \leq n, m \leq 120ai,j10 \leq a_{i,j} \leq 1

代码解析

简而言之,可选择的矩形区域必须全都是 1,只需要以每个点 arr[i][j] 作为起点,再以这个点为矩形左上角,依次枚举右下角的点 arr[x][y],遍历这个矩形区域,看这个区域内是否全部都是 1,如果全部都是 1 则统计这个矩形区域内点的数量 (x-i+1)*(y-j+1),求最大值。

#include<bits/stdc++.h>
using namespace std;
bool arr[15][15] = {0};
int n, m;
// 封装 sum 函数统计以 arr[i][j] 作为左上角的矩形中全是 1 的最大矩形
int sum(int i, int j) {
int cnt = 0;
for(int x = i; x <= n; x++)
for(int y = j; y <= m; y++) {
bool flag = true;
for(int a = i; a <= x; a++)
for(int b = j; b <= y; b++)
if (arr[a][b] == 0)
flag = false;
if (flag)
cnt = max(cnt, (x-i+1)*(y-j+1));
}
return cnt;
}
int main() {
cin >> n >> m;
int ans = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> arr[i][j];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
ans = max(ans, sum(i, j));
}
cout << ans;
return 0;
}

202509-2 最长连续段#

题目描述

对于 kk 个整数构成的数组 [b1,b2,,bk][b_1, b_2, \ldots, b_k],如果对 1i<k1 \leq i < k 都有 bi+1=bi+1b_{i+1} = b_i + 1,那么称数组 bb 是一个连续段。

给定由 nn 个整数构成的数组 [a1,a2,,an][a_1, a_2, \ldots, a_n],你可以任意重排数组 aa 中元素顺序。请问在重排顺序之后,aa 所有是连续段的子数组中,最长的子数组长度是多少?

例如,对于数组 [1,0,2,4][1, 0, 2, 4],可以将其重排为 [4,0,1,2][4, 0, 1, 2],有以下 1010 个子数组:

[4],[0],[1],[2],[4,0],[0,1],[1,2],[4,0,1],[0,1,2],[4,0,1,2][4], [0], [1], [2], [4, 0], [0, 1], [1, 2], [4, 0, 1], [0, 1, 2], [4, 0, 1, 2]

其中除 [4,0],[4,0,1],[4,0,1,2][4, 0], [4, 0, 1], [4, 0, 1, 2] 以外的子数组均是连续段,因此是连续段的子数组中,最长子数组长度为 3。

输入格式

第一行,一个正整数 nn,表示数组长度。

第二行,nn 个整数 a1,a2,,ana_1, a_2, \ldots, a_n,表示数组中的整数。

输出格式

一行,一个整数,表示数组 aa 重排顺序后,所有是连续段的子数组的最长长度。

样例输入 1

4
1 0 2 4

样例输出 1

3

样例输入 2

9
9 9 8 2 4 4 3 5 3

样例输出 2

4

提示

对于 40%40\% 的测试点,保证 1n81 \leq n \leq 8

对于所有测试点,保证 1n1051 \leq n \leq 10^5109ai109-10^9 \leq a_i \leq 10^9

代码解析

连续段的意思是 1,2,3,4 …

解题思路就是先对原数组进行排序,然后确定一个变量 last 来记录上一个数字,如果数 a[i] == last ,就跳过继续找,如果 a[i] == last + 1 则连续段长度加 1,如果 a[i] 小于 last 或大于 last + 1 说明当前连续段已经最长,记录最大值,重新开始统计下一个连续段

#include<bits/stdc++.h>
using namespace std;
int main() {
int a[100005];
int n;
cin >> n;
for(int i = 0; i < n; i++)
cin >> a[i];
sort(a, a+n);
int last = a[0], m = 1, cnt = 1;
for(int i = 1; i < n; i++) {
if (a[i] == last) {
continue;
} else if (a[i] == last + 1) {
m++;
last = a[i];
} else {
cnt = max(cnt, m);
m = 1;
last = a[i];
}
}
cnt = max(cnt, m);
cout << cnt;
return 0;
}
GESP 2025年C++四级编程题解析
https://yezi.press/posts/gesp/gesp-cpp4-2025/
作者
Yezi 叶子
发布于
2025/03/22
许可协议
CC BY-NC-SA 4.0