洛谷P1325 雷达安装
题目
https://www.luogu.com.cn/problem/P1325
思路
挺巧妙的一道题,刚开始又是想贪心,又是考虑决策单调性想搞DP,一直在想怎么把一个雷达覆盖的点最大化。
后来画了一下图,发现如果从岛屿的角度思考这题就很好做了。
首先,雷达必然在x轴上最优。(不解释)
我们发现,对于一个岛屿来说,能覆盖他的雷达位置的可行区间是一条线段,且其左右端点可以根据勾股定理计算。
那么,问题就转化成了,有若干条线段,要求放置一些点,使得每条线段上都至少有一个点。这就是一个经典的贪心问题了。
将线段按右端点从小到大排序,如果当前线段未被之前的点覆盖,就在该线段的最右端放一个点。
代码
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn (int)(2e6+10)
#define eps 1e-8
#define inf 0x3f3f3f3f
using namespace std;
struct point{
int x,y;
} p[maxn];
struct line{
double L,R;
bool operator <(line t){
return R<t.R;
}
} l[maxn];
int main(){
int n,d,flag=1,ans=0;
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
l[i].L=p[i].x-sqrt(d*d-p[i].y*p[i].y);
l[i].R=p[i].x+sqrt(d*d-p[i].y*p[i].y);
}
sort(l+1,l+n+1);
for(int i=1;i<=n;i++){
if(p[i].y>d){
flag=0;
break;
}
}
if(flag){
double last=-inf;
for(int i=1;i<=n;i++){
if(l[i].L-eps>last){
ans++;
last=l[i].R;
}
}
}
else{
ans=-1;
}
printf("%d",ans);
// system("pause");
return 0;
}