1. 程式人生 > >UVA 10382 Watering Grass(區間覆蓋,貪心)題解

UVA 10382 Watering Grass(區間覆蓋,貪心)題解

set lan cstring align mes sqrt 2.0 vector 最大

題意:有一塊草坪,這塊草坪長l 米,寬 w 米,草坪有一些噴頭,每個噴頭在橫坐標為 p 處,每個噴頭的縱坐標都是(w/2) ,並且噴頭的灑水範圍是一個以噴頭為圓心,半徑為 r 米的圓。每次最少需要打開多少個噴頭來給草坪灑水,並且草坪各處都能被灑到,不行輸出-1

思路:這是一道區間覆蓋(貪心)題:

有一堆區間 l1, r1;l2, r2...ln,rn,問你最少用幾個能覆蓋0~P的長度

那麽我們先按照L升序排序,far是目前所能找到的最遠處,R是上一次查詢所能找到的最遠處,每次查詢我們都要找後面滿足li <= R的點,記錄far,當這一輪查找完畢後R = far。顯然R初始化應為最左端的點(本題為0)。

比如區間為[-1,4],[0,2],[0,1],[2,4],[2,6],[3,5],[3,6],[3,7],[6,8],覆蓋區域為0~8

第一步選擇[-1,4],[0,2],[0,1]中最遠的[-1,4] ,那麽下一步能夠選擇的有[2,6],[3,5],[3,6],[3,7],由於7最大,所以下一步選擇[3,7],最後一步只能選擇[6,8]

這一題註意篩選 r < w 情況。

代碼:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include
<vector> #include<string> #include<cstdio> #include<cstring> #include<sstream> #include<iostream> #include<algorithm> typedef long long ll; using namespace std; const int maxn = 10000 + 10; const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; struct node{
double l, r; bool operator < (const node x) const{ return l < x.l; } }a[maxn]; int n; double l, w; int solve(){ sort(a + 1, a + n + 1); double far = 0, R = 0; int ans = 0, pos = 1; while(pos <= n){ if(far >= l) break; if(a[pos].l <= R){ ans++; while(a[pos].l <= R && pos <= n){ far = max(far, a[pos].r); pos++; } R = far; } else break; } if(far >= l) return ans; return -1; } int main(){ while(~scanf("%d%lf%lf", &n, &l, &w)){ w /= 2.0; for(int i = 1; i <= n; i++){ double p, r, del; scanf("%lf%lf", &p, &r); if(r >= w){ double s = sqrt(r * r - w * w); a[i].l = p - s; a[i].r = p + s; } else{ i--; n--; } } printf("%d\n", solve()); } return 0; }

UVA 10382 Watering Grass(區間覆蓋,貪心)題解