程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 1328 Radar Installation(貪心)

POJ 1328 Radar Installation(貪心)

編輯:C++入門知識

題目鏈接:http://poj.org/problem?id=1328

題目大意是在直線海岸線周圍有小島,建設雷達把小島覆蓋,但是雷達有直徑,要求建造最少的雷達。

很明顯就是一個貪心,就這題困了兩天;

剛開始我是打算,先按照X坐標以小到大,Y坐標以大到小排序,然後從最左上的小到開始,以每個小島為圓心,d(雷達半徑)為半徑畫圓,求出與海岸線交點然後以最右邊的交點建雷達,然後向右遍歷,如果在雷達范圍內的小島continue,否則在建,以此循環。就這樣死腦筋了好久,一直都不相信這樣是錯的。最後終於發現了漏洞。

如果有這樣的數據:

半徑d = 5

有兩個島嶼,坐標分別是:

X1 = -2,Y1 =4;

X2 = 0,Y2 = 5;

用我的思路就會像下圖的情況:

\

紅圈是島嶼以d為半徑畫的,此時,我的思路會把先建雷達1,然後判斷雷達1與小島2的距離判斷,發現不滿足,然後又建立了雷達2,最終結果的2個

但是只需要在原點建立雷達就足夠了,因此,這個思路是錯誤的。

我又重新構思了思路,我們可以以島嶼為圓心d為半徑得出在建雷達的陸地區間來,然後幾個島嶼疊加來獲得重復區間。

讓每個重復區間的島嶼盡量多,也就是讓每個雷達覆蓋盡量多的島嶼,這就是貪心所在。

還是這組數據,我們就得到這樣兩個區間,【-5,0】,【0,0】,然後疊加就是【0,0】;<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+yOfNvKO6PC9wPgo8cD48aW1nIHNyYz0="http://www.2cto.com/uploadfile/Collfiles/20140607/20140607091149387.jpg" alt="\">

藍色線就是第一個島嶼的區間,粉紅點就是雷達(疊加區間)所在。

因為這個疊加區間存在,所以一個雷達足以,反之,如果不存在,就需要新建雷達,並以最右的點再得區間。

這樣,代碼如下:

#include 
#include 
#include 
#include 

struct L
{
    double l,r;
}lim[10000];

int cmp(const void *a,const void *b)
{
    struct L *ta = (struct L *)a;
    struct L *tb = (struct L *)b;


    return ta->l > tb->l ? 1 : -1;
}

int main()
{
    int n,d;
    int i,k;
    int NO = 0;

    while (~scanf ("%d%d",&n,&d) && (n || d))
    {
        int tf = 0;

        for (i = 0; i < n;i++)
        {
            double x,y;
            scanf ("%lf%lf",&x,&y);
            if (y > d)
                tf = 1;

            lim[i].l = x - sqrt (d * d - y * y);
            lim[i].r = sqrt (d * d - y * y) + x;
        }

        if (tf)
        {
            printf ("Case %d: -1\n",++NO);
            continue;
        }

        qsort (lim,n,sizeof (lim[0]),cmp);
        int ans = 1;
        double s = lim[0].r;

        for (i = 1;i < n;i++)
        {
            if (lim[i].l > s)
            {
                s = lim[i].r;
                ans++;
            }else
            {
                s = s < lim[i].r ? s : lim[i].r;    //就因為這裡,WA了近10次
            }
        }

        printf ("Case %d: %d\n",++NO,ans);
    }
    return 0;
}


博客:http://blog.csdn.net/codehypo

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved