题解:P10913 [蓝桥杯 2024 国 B] 套手镯
Sweet_2013 · · 题解
我的思考过程:
这道题的考点是贪心,双指针,扫描线,优先队列。
题面翻译:
给我们
做法:
首先对于矩形的放置,我们有两个维度需要考虑——
但是,我们发现
那怎么固定呢?其实仔细思考一下,在最优的矩形放置策略中,我们是不是将矩形的底部刚好与某个圆的底部相切是最优的。其实显然,因为上诉操作会尽可能的留空间给上面的圆形(这也是我认为考点有贪心的点)。因此,对于固定的
可以先将圆按照右端点升序排序,然后双指针,对于
因此,我们需要用一个优先队列对在矩形中的圆的最左端点进行维护,这样在遍历右端点的时候我们可以及时且高效地将左端点越出矩形左边界的点删除。然后依次遍历维护最大点数(优先队列的大小的最大值)即可。
附上代码:
#include<bits/stdc++.h>
using namespace std;
struct node{
int x, y, r;
bool operator <(node a){
return x + r < a.x + a.r;
}
}p[1001];
int ys[1001], n, w, h, ans;
int slv(int ed){
priority_queue<int, vector<int>, greater<int>>q;
int ans = 0;
for(int i = 0; i < n; i++){
//invalid
if(p[i].y - p[i].r < ed || p[i].y + p[i].r > h + ed)continue;
if(2 * p[i].r > w)continue;
int last = p[i].x + p[i].r;
while(q.size() && last - q.top() > w) q.pop();
int l = p[i].x - p[i].r;
q.push(l);
ans = max(ans, (int)q.size());
}
return ans;
}
int main(){
cin >> n >> w >> h;
for(int i = 0; i < n; i++){
cin >> p[i].x >> p[i].y >> p[i].r;
ys[i] = p[i].y - p[i].r;
}
sort(p, p + n);
sort(ys, ys + n);
for(int i = 0; i < n; i++) ans = max(ans, slv(ys[i]));
swap(w, h);
for(int i = 0; i < n; i++) ans = max(ans, slv(ys[i]));
cout << ans << endl;
return 0;
}