202509-1 排兵布阵
题目描述
作为将军,你自然需要合理地排兵布阵。地图可以视为 行 列的网格,适合排兵的网格以 1 标注,不适合排兵的网格以 0 标注。现在你需要在地图上选择一个矩形区域排兵,这个矩形区域内不能包含不适合排兵的网格。请问可选择的矩形区域最多能包含多少网格?
输入格式
第一行,两个正整数 ,分别表示地图网格的行数与列数。
接下来 行,每行 个整数 ,表示各行中的网格是否适合排兵。
输出格式
一行,一个整数,表示适合排兵的矩形区域包含的最大网格数。
样例输入 1
4 30 1 11 0 10 1 11 1 1
样例输出 1
4
样例输入 2
3 51 0 1 0 10 1 0 1 00 1 1 1 0
样例输出 2
3
提示
对于所有测试点,保证 ,。
代码解析
简而言之,可选择的矩形区域必须全都是 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 最长连续段
题目描述
对于 个整数构成的数组 ,如果对 都有 ,那么称数组 是一个连续段。
给定由 个整数构成的数组 ,你可以任意重排数组 中元素顺序。请问在重排顺序之后, 所有是连续段的子数组中,最长的子数组长度是多少?
例如,对于数组 ,可以将其重排为 ,有以下 个子数组:
其中除 以外的子数组均是连续段,因此是连续段的子数组中,最长子数组长度为 3。
输入格式
第一行,一个正整数 ,表示数组长度。
第二行, 个整数 ,表示数组中的整数。
输出格式
一行,一个整数,表示数组 重排顺序后,所有是连续段的子数组的最长长度。
样例输入 1
41 0 2 4
样例输出 1
3
样例输入 2
99 9 8 2 4 4 3 5 3
样例输出 2
4
提示
对于 的测试点,保证 。
对于所有测试点,保证 ,。
代码解析
连续段的意思是 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;}