蓝桥杯2024年第十五届决赛真题-套手镯

小蓝在 LQ 集市上发现一个套手镯的游戏,在一个大小为 1e8 × 1e8 矩形平面上摆放着 N 个圆形的手镯。玩家可以将一个大小为 w × h 的矩形方框放置在这个平面上(玩家只可以沿着水平/垂直方向放置方框,即可以将方框旋转 90度,但不可以旋转至其他角度),位于这个矩形方框内部的手镯就是玩家获得的奖励。

可以将这个矩形平面看作是一个二维坐标系,左下角的坐标为 (0, 0)。手镯和方框的厚度可以忽略不计, 允许多个手镯重叠放置。

小蓝想要尝试一次,请问他最多可以获得多少手镯?

输入格式

第一行输入三个整数 N、w、h。

接下来输入 N 行,每行三个整数 x, y,r,表示第 i 个手镯的圆心坐标和半径。

输出格式

输出一个整数表示答案。

样例输入

复制代码
8 12 9
18 22 1
3 17 2
21 28 1
7 18 2
10 2 2
4 24 2
19 13 1
14 15 1

样例输出

复制代码
3

提示

【评测用例规模与约定】

对于 50% 的评测用例:1 ≤ N ≤ 100,1 ≤ w, h, x, y,r ≤ 200。

对于 100% 的评测用例:1 ≤ N ≤ 1000,1 ≤ w, h, x, y,r ≤ 1e8,1 ≤min{w, h} ≤ 200。保证所有手镯都位于平面内部。

//这道题显然对于某些点能否共同待在一个矩形内是好判断的,但是难点就在于自己并不知道该选哪一堆点,根据数据规模暴搜的话绝对从超时,那咋办?我们首先对于每个点进行处理,显然每个圆都有上下左右四个边界,我们收集起来然后按照右边界升序排序。然后不妨转换下思路,我们可以把研究方向从点上转移到矩形位置上,我们大可以枚举矩形的位置不是吗?但是也不是暴力枚举,我们只枚举那些有必要的位置,那什么是有必要的位置,就是与某个圆相切绝对是最好情况。我们不妨外部循环枚举矩形的下边界,也就是每一个圆的下边界(因为正好相切),这样上边界其实也就确定了,那么内部循环枚举的就是每一个点,判断其是否在矩形的上下范围之内,如果在就加入一个堆中,该堆按照圆的左边界升序排列。当然上下范围符合那还要判断左右范围是否符合,那这就体现了刚才为啥要引入堆,堆顶的左边界显然最小,如果堆顶左边界与当前遍历到的节点(不用管当前节点是否在堆中,因为我们的每个圆是按照右边界升序排序的,如果当前点都不能满足,后续一定不会满足)的右边界差的绝对值超过规定,那就不断弹出堆。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10; // 定义数组大小的上限

const int MOD = 1e9 + 7; // 常用的大质数MOD

ll n, w, h; // n是手镯数量,w和h是矩形的宽度和高度

// 定义结构体Node表示一个手镯的四个边界

struct Node {

int l, r, b, t; // 左、右、下、上边界

// 重载小于运算符,按照左边界从大到小排序,优先队列中会保持左边界从小到大排列

bool operator< (const Node &u) const {

return l > u.l;

}

} a[N];

// solve函数:计算矩形区域内可以容纳最多的手镯数

int solve(int tw, int th) {

int res = 0; // 记录结果(最大手镯数)

// 外层循环:固定矩形的下边界line

for (int i = 0; i < n; i++) {

int bottom = a[i].b; // 当前手镯的下边界

int top = bottom + th; // 计算矩形的上边界

priority_queue<Node> q; // 优先队列,用来存储在当前上下边界之内的手镯

// 内层循环:检查所有手镯是否在当前的上下边界范围内

for (int j = 0; j < n; j++) {

// 如果手镯的上下边界在当前矩形范围内

if (a[j].b >= bottom && a[j].t <= top) {

q.push(a[j]); // 将符合条件的手镯加入优先队列

}

// 移除不再符合当前左右边界范围的手镯

while (!q.empty() && q.top().l < a[j].r - tw) {

q.pop(); // 移除左边界小于当前手镯右边界-矩形宽度的手镯

}

// 更新最大值,计算当前矩形内的手镯数量

res = max(res, (int)q.size());

}

}

return res; // 返回最大手镯数

}

// cmp函数:按照手镯右边界从小到大排序

bool cmp(Node a, Node b) {

return a.r < b.r;

}

int main() {

cin >> n >> w >> h; // 输入手镯数量n和矩形的宽度w和高度h

// 输入每个手镯的坐标和半径,并计算出每个手镯的四个边界

for (int i = 0; i < n; i++) {

int x, y, r;

cin >> x >> y >> r; // 输入手镯的中心坐标(x, y)和半径r

a[i].l = x - r; // 计算左边界

a[i].r = x + r; // 计算右边界

a[i].b = y - r; // 计算下边界

a[i].t = y + r; // 计算上边界

}

sort(a, a + n, cmp); // 根据右边界升序排序所有手镯

// 分别尝试两种矩形方向,w x h 和 h x w

int res1 = solve(w, h);

int res2 = solve(h, w);

// 输出两种方向中的最大手镯数

cout << max(res1, res2) << endl;

return 0;

}

相关推荐
Σίσυφος19002 小时前
E = Kᵀ F K 的数学原理
算法
王老师青少年编程2 小时前
2022年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第3题)
c++·题解·真题·初赛·信奥赛·csp-s·提高组
小O的算法实验室2 小时前
2025年JIM SCI2区,基于Q学习多目标粒子群算法+节能型分布式流水车间调度,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
YunchengLi2 小时前
【计算机图形学中的四元数】1/2 Quaternions for Computer Graphics
人工智能·算法·机器学习
良木生香2 小时前
【C++初阶】C++入门相关知识(1):C++历史 & 第一个C++程序 & 命名空间
c语言·开发语言·c++
重生之后端学习2 小时前
108. 将有序数组转换为二叉搜索树
数据结构·算法·深度优先
诸葛务农2 小时前
点云配准在人形机器人中的应用:ICP算法(1)
算法·机器学习·机器人
寻寻觅觅☆10 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
fpcc10 小时前
并行编程实战——CUDA编程的Parallel Task类型
c++·cuda