题意:一块长l,宽w的长方形草坪,在其中心线的不同位置处装有n个点状的喷水装置。每个喷水装置i可将以它为中心,半径为ri的圆形区域润湿。请选择尽量少的喷水装置,把整个草坪全部润湿。
思路:变形的区间覆盖问题。其实我们只要将圆形转化为覆盖在草坪上的矩形即可。当半径ri<w/2时,圆形面积在草坪真正有用的只是一条竖线,对于完全覆盖草坪没有任何意义,所以这种喷水装置不取。转化完之后,只要按照区间覆盖问题去解决就行了。先判断是否能从开头开始覆盖,之后每次取起点相同,但是区间长度最长的那个区间(期间注意判断是否能覆盖每一个地方)。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int MAXN = 10005; struct node{ double s, e; }t[MAXN]; int n; double l, w; int cmp(node a, node b) { if (a.s != b.s) return a.s < b.s; else return a.e > b.e; } int main() { while (scanf("%d%lf%lf", &n, &l, &w) != EOF) { int cnt = 0; for (int i = 0; i < n; i++) { double p, r; scanf("%lf%lf", &p, &r); if (r > w / 2) { double temp = sqrt(r * r - w * w / 4); t[cnt].s = p - temp; t[cnt].e = p + temp; cnt++; } } sort(t, t + cnt, cmp); int num = 0, flag = 0; double start = 0, end = 0; if (t[0].s <= 0) { int left = 0; while (left < cnt) { int right = left; while (right < cnt && t[right].s <= start) { if (t[right].e >= end) end = t[right].e; right++; } if (right == left) { break; } num++; left = right; start = end; if (start >= l) { flag = 1; break; } } } if (flag) printf("%d\n", num); else printf("-1\n"); } return 0; }
UVA10382- Watering Grass(区间覆盖问题)
时间: 2024-10-02 00:44:49