題意:
噴水裝置能否覆蓋草坪,其實隻取決於圖中每個圓藍色部分能否將草坪覆蓋,這樣我們就將問題轉化成了有若幹線段,求覆蓋一個指定區間最少要多少條線段
分析:
題目可以作出如下轉化:

從最左開始使用貪心策略每次選擇一個包含當前最右的區間且擴張最遠的圓
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;
}

本文介绍了一种通过贪心策略解决喷水装置如何最小数量覆盖指定区域的问题。将问题转化为线段覆盖问题,并通过从左至右选择能够最大程度扩展覆盖范围的线段来实现。
4145

被折叠的 条评论
为什么被折叠?



