ACM 噴水裝置(二)

OpenSoucre發表於2014-04-17

噴水裝置(二)

時間限制:3000 ms  |  記憶體限制:65535 KB
難度:4
 
描述
有一塊草坪,橫向長w,縱向長為h,在它的橫向中心線上不同位置處裝有n(n<=10000)個點狀的噴水裝置,每個噴水裝置i噴水的效果是讓以它為中心半徑為Ri的圓都被潤溼。請在給出的噴水裝置中選擇儘量少的噴水裝置,把整個草坪全部潤溼。
 
輸入
第一行輸入一個正整數N表示共有n次測試資料。
每一組測試資料的第一行有三個整數n,w,h,n表示共有n個噴水裝置,w表示草坪的橫向長度,h表示草坪的縱向長度。
隨後的n行,都有兩個整數xi和ri,xi表示第i個噴水裝置的的橫座標(最左邊為0),ri表示該噴水裝置能覆蓋的圓的半徑。
輸出
每組測試資料輸出一個正整數,表示共需要多少個噴水裝置,每個輸出單獨佔一行。
如果不存在一種能夠把整個草坪溼潤的方案,請輸出0。
樣例輸入
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5
樣例輸出
1
2
區間覆蓋問題分成三種情況(“---”表示區間)
第一種情況
a -----------
b --------------
c -----------
此時沒有能覆蓋b和c之間的區域
第二種情況
 a -----------
b ------------
c -------------
此時需要選擇a,b,c三個區間
第三種
 a -----------
b -------------
c ---------------
此時選擇a,c兩個區間就能覆蓋住,不需要選擇3個區間
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

struct Segment{
    double first,second;
    Segment(double first_ = 0, double second_ = 0):first(first_),second(second_){}
    bool operator < (const Segment& a) const{
        if(first!=a.first) return first < a.first;
        else return second > a.second;
    }
};

int main(){
    int N;
    cin >>N;
    for(int icase = 0 ; icase < N; icase ++ ){
        int n;
        double w,h;
        cin >> n >>w >> h;
        vector<Segment> segments;
        for(int i = 0 ; i < n; ++ i){
            double x,r;
            cin >> x >>r;
            if(2*r >= h){
                segments.push_back(Segment(x - sqrt(4*r*r-h*h)/2,x + sqrt(4*r*r-h*h)/2));
            }
        }
        sort(segments.begin(),segments.end());
        int cnt = 1;
        double left = segments[0].first, right = segments[0].second, prevRight = 0;
        for(int i = 1 ; i < segments.size(); ++ i){
            if(segments[i].first > right ){                   // 第一種情況
                cnt = 0;
                break;
            }else if(segments[i].first  >= prevRight){       //第二種情況
                cnt++;
                prevRight = right;
                right = segments[i].second;
            }else if(segments[i].first < prevRight && segments[i].second > right){    //第三種情況
                 right = segments[i].second;
            }
            if(right >= w) break;
        }
        if(left<= 0 && right >= w) cout<<cnt<<endl;
        else cout<<0<<endl;
    }
}

 

 
 

相關文章