/*
重要结论:
如果可以找到一个雷达同时覆盖多个区间,那么把这多个区间
按照起点坐标从小到大排序,则最后一个区间(起点最靠右的)
k的起点,就能覆盖所有区间。
证明:如果它不能覆盖某个区间x,那么它必然位于
1)x起点的左边,或者 2)x终点的右边
情况1)和k的起点是最靠右的矛盾
情况2)如果发生,则不可能找到一个点同时覆盖x和k,
也和前提矛盾,有了这个结论,就可以只挑区间的起点
来放置雷达了。
贪心算法:
1)将所有的区间起点从小到大排序,并编号0-(n-1)
2)一次考察每个区间的起点,看要不要再哪里放雷达。开始,
所有区间都没被覆盖,所以目前编号最小的未被覆盖的区间的编号
firstNoConverd=0
-----------now1
-----now2
1-----------
----------
--------------
2---------------
3----------
3)考察一个区间i的起点Xi的时候,要看从firstNoCovered
到区间i-1中是否存在某个区间c,没有被Xi覆盖。如果没有,
则先不急于在Xi放雷达,接着往下看。如果有,那么c的终点
肯定在Xi的左边,因此不可能用同一个雷达覆盖c和i。即能覆盖c的点,
已经不可能覆盖i和i后面的区间了。此时,为了覆盖c,
必须放一个雷达了,放在区间i-1的起点即可覆盖
所有从firstNoCovered到i-1的区间。因为当初考察i-1的起点z时候,
并没有发现z漏覆盖了从firstNoCovered到i-2之间的任何一个区间。
4)放完雷达后,将firstNoCovered改为i,再做下去。
复杂度:O(n*n)
证明:
替换法:考虑不用贪心法获得的最佳雷达摆放方案。将其所有雷达按坐标
从小到大排列得到X1,X2,,,用贪心法得到的雷达坐标从小到大排序则为
y1,y2
可证明每个Xi都可以被Yi替换,且y序列不会比x序列长,先证明x1可以用y1替换。
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
struct node{
double l,r;
}a[1111];
int t,n,d;
bool cmp(node a,node b){
return a.l<b.l;
}
int solve(){
int ans;
double now;
sort(a,a+n,cmp);
ans=1;
now=a[0].r;
for(int i=1;i<n;++i){
if(a[i].l<=now)now=min(now,a[i].r);
else{
ans++;
now=a[i].r;
}
}
return ans;
}
int main(){
int x,y;
bool flag;
t=0;
while(true){
++t;
cin>>n>>d;
if(n==0&&d==0)break;
flag=true;
for(int i=0;i<n;++i){
cin>>x>>y;
if(y>d)flag=false;
else{
a[i].l=x-sqrt(d*d-y*y);
a[i].r=x+sqrt(d*d-y*y);
}
}
if(flag)cout<<"Case "<<t<<": "<<solve()<<endl;
else cout<<"Case "<<t<<": "<<-1<<endl;
}
return 0;
}
OpenJudge1328:Radar Installation
最新推荐文章于 2019-06-15 20:17:32 发布