浇水
浇水 (贪心 ⋆)
- 在一条长 n 米,宽 m 米的长方形草地上放置着 k 个喷水装置。假设长方形草地的坐标范围为[0,0]∼[n,m] ,那么第i个喷水装置的位置为 (ai,m2),也就是说喷水装置全部位于一条直线上。此外第 i 个喷水装置能向半径ri 的圆形区域内喷水。
- 负责管理喷水装置的园丁老大爷想知道,要想覆盖整个草地,至少需要开启多少个喷水装置。
Input
- 第一行三个正整数 k,n 和 m 。其中 m 为偶数。
- 接下来 k 行,每行两个整数 ai 和 ri,代表第 i 个喷水装置的横坐标和喷水半径。
Output
- 一个整数 ans 代表至少需要开启的喷水装置数量。若所有装置都开启依然不能覆盖整个草地则输出 −1。
Sample Input1
9 16 6
0 5
2 5
4 5
6 5
8 5
10 5
12 5
14 5
16 5
Sample Output1
2
Sample Input2
8 20 2
5 3
4 1
1 2
7 2
10 2
13 3
16 2
19 4
Sample Output2
6
Hint
- 样例 1 解释开启位于 4 和 12 的喷水装置即可。
- 30% 的数据中: k≤20;
- 另有 20% 的数据中: ri 均相等;
- 100% 的数据中: m≤20000,ri≤10000,n,k≤105,ai≤n。
分析
- 喷水装置在长方形的中线上,如果某个喷水装置能喷到左上角的地方,那左下角必定能喷到。
- 如果喷水装置的喷水半径小于 h2 此装置无用。
- 所以我们可以预处理出每一个喷水装置能喷到的左、右最远的距离,然后对其左边界进行排序,从左到右,一次枚举花坛的未喷到的最远点,在能喷到的装置中找到右端点最远的装置。
Code
#include <bits/stdc++.h>
const int maxn=1e5+5;
int n,N,lenth,high;
struct Node{
double L,R;
}a[maxn];
bool cmp(const Node& a,const Node& b){
return a.L < b.L;
}
void Read(){
scanf("%d%d%d",&n,&lenth,&high);
N = 0;
for(int i = 1;i <= n;i++){
int x,r;scanf("%d%d",&x,&r);
if(r <= high/2)
continue;
a[++N].L = x - sqrt(r*r - high*high/4.0);
a[N].R = x + sqrt(r*r - high*high/4.0);
}
std::sort(a+1,a+N+1,cmp);
}
void Solve(){
double tail= 0;//记录已经浇到最右的距离
int ans = 0,i = 1;
while(tail < lenth){
ans++;
double s = tail;//记录未浇到的最右点
for(;i<= N && a[i].L <= s;i++)
if(tail < a[i].R)//能浇到s,就选尽量右的
tail=a[i].R;
if(tail==s && s<lenth){//找不到能浇到s的点
printf("-1\n");
return;
}
}
printf("%d\n",ans);
}
int main(){
Read();
Solve();
return 0;
}
hzoi
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步