方法:贪心。
思路:对于每一个小岛,岸上的雷达位置都有一个固定范围,只有在这个范围内,才能监测到。假设小岛分别是i1,i2,..,in,对应的雷达范围是:(x1,y1),(x2,y2),...,(xn,yn),先对雷达范围按x排序,得到:
s1(x1',y1'),s2(x2',y2'),...,sn(xn',yn')。分析:如果s1和s2有交集[p1,p2],说明雷达在[p1,p2]任意位置即可,为了雷达尽可能少,应放在最右面,即p2(但此时要注意,如果x2'==y2',即该小岛到海岸线的垂直距离正好是d,则监测点必须在y2'处);如果没有交集,s1必须有个雷达,s2也必须有个雷达。以此类推,用一个变量right记录当前要建雷达的最右位置。
PS:又是一道用C++就AC,用G++就TLE的题。不懂原因。
#include<iostream>
#include<cmath>
using namespace std;
int n;
double d;
double island[1000][2];
double region[1000][2];
int res;
void qsort(int left,int right)
{
if(left<right)
{
int i=left,j=right;
double x=region[i][0],y=region[i][1];
while(i<j)
{
while(i<j&®ion[j][0]>=x)
{
j--;
}
if(i<j)
{
region[i][0]=region[j][0];
region[i][1]=region[j][1];
i++;
}
while(i<j&®ion[i][0]<x)
{
i++;
}
if(i<j)
{
region[j][0]=region[i][0];
region[j][1]=region[i][1];
j--;
}
}
region[i][0]=x;
region[i][1]=y;
qsort(left,i-1);
qsort(i+1,right);
}
}
void greedy()
{
int i;
double right=region[0][1];
res=1;
for(i=1;i<n;i++)
{
if(region[i][0]<=right)
{
right=(region[i][1]>right)?right:region[i][1];
}
else
{
res++;
right=region[i][1];
}
}
}
int main()
{
int i,flag,num=0,index=0;
cin>>n>>d;
while(n!=0&&d!=0)
{
index++;
flag=0;
for(i=0;i<n;i++)
{
cin>>island[i][0]>>island[i][1];
if(island[i][1]>d || island[i][1]<0 || d<0)
{
flag=1;
}
region[i][0]=island[i][0]-sqrt(d*d-island[i][1]*island[i][1]);
region[i][1]=island[i][0]+sqrt(d*d-island[i][1]*island[i][1]);
}
if(flag==1)
{
cout<<"Case "<<index<<": -1"<<endl;
cin>>n>>d;
continue;
}
qsort(0,n-1);
greedy();
cout<<"Case "<<index<<": "<<res<<endl;
cin>>n>>d;
}
return 0;
}