1. 程式人生 > >區間貪心

區間貪心

題目大意:以x軸為分界,y>0部分為海,y<0部分為陸地,給出一些島嶼座標(在海中),再給出雷達可達到範圍,雷達只可以安在陸地上,問最少多少雷達可以覆蓋所以島嶼
本題貪心思路是把點轉化為在x軸座標上的區間(即能保證覆蓋該小島的雷達所有可能位置的集合),然後按點的順序排也行,按左端點排也行。然後最左邊的依次向右遍歷,如果下一個區間的最左端在上一個雷達的右端,顯然需要放一個新雷達;如果在左端的話,則需要判斷最右端了,如果最右端也在上個雷達左端的話,那麼這個雷達顯然不能覆蓋當前這個小島,需要把雷達位置調整為當前區間的最右端,這樣既能覆蓋之前的也能覆蓋現在的;如果最右端在上個雷達右端,則無需調整也無需放置新雷達。
--------------------- 
作者:詹明捷 
來源:CSDN 
原文:https://blog.csdn.net/ACM_10000h/article/details/41009307 
版權宣告:本文為博主原創文章,轉載請附上博文連結!

題意:雷達如何放置?在xoy二維平面座標系裡面,x軸上方的為島嶼,x軸下方的是雷達要放到位置,如何放使得雷達放的最少?

思路

  1. 肯定放在x軸上減少浪費是最好的選擇
  2. 什麼情況下,雷達無法到達呢?--以這個島嶼為圓心,d為半徑,如果這個圓與x軸沒有交點的話,就是無法覆蓋到---即y>d
  3.   現在就可以這麼想了,每個島嶼都當成圓心C,然後都取畫圓,跟x軸的交點例如交點A,B.如果雷達放到AB之間那就是可以將剛才C覆蓋住了。--轉為區間貪心問題

區間貪心問題:

  1. 先將各個區間的左端點按照從小到大排序
  2. 然後按遞增序列開始選取區間,有兩種情況 例項說明
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;
    }
}