POJ-1328 Radar Installation题解
Radar Installation(贪心)
题意
假设在一条无限延伸的\(x\)轴上方存在\(n\)个点,现问是否能用多个在圆心在\(x\)轴上,半径为\(d\)的圆包含所有的点,若可以,输出最少的使用个数,不行则输出\(-1\)。
思路
先考虑不行的情况,只要点的离\(x\)轴的高度超过圆的半径\(d\),就不可能用圆来覆盖。
接下来,我们可以先想一下两个点的情况,什么时候需要增加新的圆?设两个点分别为\(A、B\),并假设\(B\)在\(A\)的右侧。能圈住\(A\)点并且向右覆盖范围最大的是当\(A\)点在圆上,此时圆心\(X_A\)的位置最靠右,只要\(B\)离圆心的距离大于半径,并且能圈住\(B\)并向右覆盖范围最大的圆的圆心\(X_B\)在点\(X_A\)的右侧,就需要新增加圆。其余的情况只需要调整\(X_A\)的位置,就可以覆盖到\(B\)点。
参考代码
点此展开
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const double eps=1e-6;
const int N=1010;
struct node
{
double x,y;
bool operator<(const node &a)
{
return x<a.x;
}
}ns[N];
double get_pos(double y,double d)
{
return sqrt(d*d-y*y);
}
double calc_dis(double cur,double x,double y)
{
return sqrt(y*y+(x-cur)*(x-cur));
}
int main()
{
#ifdef LOCAL
freopen("D:/VSCodeField/C_Practice/a.in", "r", stdin);
freopen("D:/VSCodeField/C_Practice/a.out", "w", stdout);
#endif
int kase=0;
int n;
double d;
while(cin>>n>>d)
{
if(n==0&&d<eps)
break;
bool has=false;//是否有点不能被覆盖
for(int i=0;i<n;i++)
{
cin>>ns[i].x>>ns[i].y;
if(ns[i].y-d>eps)
has=true;
}
cout<<"Case "<<++kase<<": ";
if(has) cout<<-1<<endl;
else
{
sort(ns,ns+n);
int res=1;
double cur=ns[0].x+get_pos(ns[0].y,d);
for(int i=1;i<n;i++)
{
double next_pos=ns[i].x+get_pos(ns[i].y,d);
if(calc_dis(cur,ns[i].x,ns[i].y)>d)
{
if(next_pos>cur)
res++;
cur=next_pos;
}
}
cout<<res<<endl;
}
}
return 0;
}