题目大意:以x轴为分界,y>0部分为海,y<0部分为陆地,给出一些岛屿坐标(在海中),再给出雷达可达到范围,雷达只可以安在陆地上,问最少多少雷达可以覆盖所以岛屿 本题贪心思路是把点转化为在x轴坐标上的区间(即能保证覆盖该小岛的雷达所有可能位置的集合),然后按点的顺序排也行,按左端点排也行。然后最左边的依次向右遍历,如果下一个区间的最左端在上一个雷达的右端,显然需要放一个新雷达;如果在左端的话,则需要判断最右端了,如果最右端也在上个雷达左端的话,那么这个雷达显然不能覆盖当前这个小岛,需要把雷达位置调整为当前区间的最右端,这样既能覆盖之前的也能覆盖现在的;如果最右端在上个雷达右端,则无需调整也无需放置新雷达。 --------------------- 作者:詹明捷 来源:CSDN 原文:https://blog.csdn.net/ACM_10000h/article/details/41009307 版权声明:本文为博主原创文章,转载请附上博文链接!
题意:雷达如何放置?在xoy二维平面坐标系里面,x轴上方的为岛屿,x轴下方的是雷达要放到位置,如何放使得雷达放的最少?
思路
- 肯定放在x轴上减少浪费是最好的选择
- 什么情况下,雷达无法到达呢?--以这个岛屿为圆心,d为半径,如果这个圆与x轴没有交点的话,就是无法覆盖到---即y>d
- 现在就可以这么想了,每个岛屿都当成圆心C,然后都取画圆,跟x轴的交点例如交点A,B.如果雷达放到AB之间那就是可以将刚才C覆盖住了。--转为区间贪心问题
区间贪心问题:
- 先将各个区间的左端点按照从小到大排序
- 然后按递增序列开始选取区间,有两种情况 实例说明
import java.util.*; public class Main { public static void main(String args[]){ Scanner in=new Scanner(System.in); int cnt_test=0; while(in.hasNext()){ cnt_test++; int n=in.nextInt(); int d=in.nextInt(); if(n==0 && d==0){ break; }else{ int num[][]=new int[n][2]; for(int i=0;i<n;i++){ num[i][0]=in.nextInt(); num[i][1]=in.nextInt(); } //判断是否存在距离x轴大于d的点,这种点将无法覆盖 int flag=0; for(int i=0;i<n;i++){ if(Math.abs(num[i][1])>d){ System.out.println("Case "+cnt_test+": -1"); flag=1; break; } } if(flag==0){ //计算每个岛屿在海岸线(x轴上的区间) List listd=new ArrayList<Point1>(); for(int i=0;i<n;i++){ double z=Math.sqrt((d*d-num[i][1]*num[i][1])*1.0); double zuo=num[i][0]*1.0-z; double you=num[i][0]*1.0+z; listd.add(new Point1(zuo,you)); } //区间排序 Collections.sort(listd, new Comparator<Point1>() { public int compare(Point1 p1,Point1 p2){ if(p1.zuo>=p2.zuo){ return 1; }else{ return -1; } } }); //计算最小点数 Point1 t0=(Point1)listd.get(0); double you=t0.you; int cnt=1; for(int i=1;i<n;i++){ Point1 ti=(Point1)listd.get(i); if(ti.zuo>you){ cnt++; you=ti.you; }else if(ti.you<you){ you=ti.you; } } System.out.println("Case "+cnt_test+": "+cnt); } } } } } class Point1{ double zuo; double you; Point1(double zuo,double you){ this.zuo=zuo; this.you=you; } }