題意:
噴水裝置能否覆蓋草坪,其實隻取決於圖中每個圓藍色部分能否將草坪覆蓋,這樣我們就將問題轉化成了有若幹線段,求覆蓋一個指定區間最少要多少條線段
分析:
題目可以作出如下轉化:
從最左開始使用貪心策略每次選擇一個包含當前最右的區間且擴張最遠的圓
Code:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 10000 + 10
#define REPI(i, s, e) for(int i = (s); i <= (e); i ++)
typedef struct QNode_ {
double x, y;
}QNode;
QNode area[MAXN];
const double eps = 1e-9;
int cal(int n, double l)
{
int cnt = 0;
double start = 0.0;
REPI(i, 1, n) {
if( area[i].x-start <= eps ) {
int idx = i, tar;
double delta = 0.0;
while( idx <= n && area[idx].x-start <= eps ) {
if( delta < area[idx].y ) {
delta = area[idx].y, tar = idx;
}
idx += 1;
}
cnt += 1;
start = area[tar].y;
if( l-start <= eps ) {
return cnt;
}
}
}
if( l-start <= eps ) {
return cnt;
}
return -1;
}
inline int cmp(const QNode &a, const QNode &b)
{
if( a.x == b.x ) {
return a.y > b.y;
}
return a.x < b.x;
}
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
#endif
int n;
double l, w, p, r;
while( ~scanf("%d %lf %lf", &n, &l, &w) ) {
REPI(i, 1, n) {
scanf("%lf %lf", &p, &r);
double delta = sqrt(r*r-w*w/4.0);
area[i].x = p-delta, area[i].y = p+delta;
}
sort(area+1, area+1+n, cmp);
printf("%d\n", cal(n, l));
}
return 0;
}