1. 程式人生 > >Uva 10382 Watering Grass(貪心區間覆蓋+)

Uva 10382 Watering Grass(貪心區間覆蓋+)

 

n sprinklers are installed in a horizontal strip of grass l meters long andw meters wide. Each sprinkler is installed at the horizontal center line of the strip. For each sprinkler we are given its position as the distance from the left end of the center line and its radius of operation.

What is the minimum number of sprinklers to turn on in order to water the entire strip of grass?


Input

Input consists of a number of cases. The first line for each case contains integer numbersn, l and w with n <= 10000. The next n lines contain two integers giving the position of a sprinkler and its radius of operation. (The picture above illustrates the first case from the sample input.)

 

Output

For each test case output the minimum number of sprinklers needed to water the entire strip of grass. If it is impossible to water the entire strip output -1.

Sample input
8 20 2

5 3

4 1

1 2

7 2

10 2

13 3

16 2

19 4

3 10 1

3 5

9 3

6 1

3 10 1

5 3

1 1

9 1

 

Sample Output

6
2

-1

 

題意:給定一條草坪。草坪上有n個噴水裝置。草坪長l米寬w米。。n個裝置都有每個裝置的位置和噴水半徑。。要求出最少需要幾個噴水裝置才能噴滿草坪。。噴水裝置都是裝在草坪中間一條水平線上的。。

思路;注意先把圓的覆蓋轉化成矩形的覆蓋,用勾股定理很簡單

      剩下的很容易想到是貪心區間覆蓋問題,但是我看了網上好幾個部落格都沒有看懂,我想的是按區間的左端點從小到大排序,然後每次都找左端點小於當前右邊界的,且右端點最大的那個點,然後將右邊界的值更新為那個右端點,依次迴圈。。。。

我覺得這才是區間覆蓋的做法吧,不明白網上那些高訪問的是啥意思。。。。

這個題的邊界資料是浮點數,所以最好不要用“=”,用精確度來表示比較好,雖然這個題好像不用也能過

剩下的東西我都寫在程式碼的註釋裡了

 

這個題我WA了十多次你敢信,真的自閉了

#include<cstdio>  
#include<algorithm>  
#include<iostream>  
#include<cmath>  
using namespace std;  
const int MAXN=10000+10;  
struct node  
{  
    double l,r;  
    /* 
    bool operator <(const sprinkler &x)const  
    {  
        return l<x.l;  
    } 
	*/ 
}sp[MAXN];  
bool cmp(const node &a,const node &b)
{
	return a.l<b.l;
}
int main()  
{  
    int n,len,w;  
    while(scanf("%d%d%d",&n,&len,&w)!=EOF)  
    {  
        int cnt=0,x;  
          
        double r,temp;    
        for(int i=0;i<n;i++)  
        {  
            scanf("%d%lf",&x,&r);  
  
            if(r*2 <= w)         //注意等號 
                continue;  
            temp=sqrt(r*r-w*w/4.0);  
            sp[cnt].l=x-temp;  
            sp[cnt].r=x+temp;  
            cnt++;  
        }  
  
        sort(sp,sp+cnt,cmp);//按最左邊的距離排序  
  
        double L=0,R=len,maxx;  
          
        int ans=0;  
        while(L<R)  
        {  
            maxx=0;  
            for(int i=0;i<cnt;i++)   
                if( sp[i].l-L <1e-16  )  
                    maxx=max(maxx,sp[i].r); //找到最大的右邊界 
  
            if(fabs(maxx-L)<1e-16)   //這裡是為了判斷maxx是不是還是上次找到的, 
            {     ans=-1; break;    }  //也就是如果沒有找到新的符合要求的點,那麼就不能覆蓋 
          
            ans++;  
            L=maxx;  
        }  
  
        printf("%d\n",ans);  
    }  
}