uva10382解题报告

来源:互联网 发布:怎么看自己淘宝联盟pid 编辑:程序博客网 时间:2024/05/29 19:30

题目大意: 在一块宽为w长为l的矩形草坪中,垂直中间有n个洒水泵,每个洒水泵的洒水区域半径为r 。求至少需要几个洒水泵才能将草坪全部洒水。具体看原题吧。


解题思路: 好吧,这个题目跟uva10020非常类似,都是典型的贪心算法题目。没看过的可以点:《uva10020解题报告》。。我们绘图来分析下这题:


经过绘图分析可知,当圆的半径小于等于w/2时,这个圆的有效区域为0. 所以在你数据输入时可以先进行预处理。同样的,我们保存每个撒水泵的数据时,转化为保存有效区域的两个边界坐标。[l,r]。 在进行贪心算法之前,我们通过排序,把所有的圆按照有效区域进行排序。从最左到最右。加快贪心算法。

AC代码如下:

#include <iostream>#include <algorithm>#include <cmath>using namespace std;const int MAXN = 10000+10;struct Node {double l;double r;}points[MAXN];int cmp(const void *p1, const void *p2) {Node n1 = *(Node *)p1;Node n2 = *(Node *)p2;if (n1.l==n2.l)return n1.r<n2.r?0:1;elsereturn n1.l<n2.l?0:1;}// 同样采用贪心算法 从最左边开始计算 void solve(int nCnt, double w, double l) {qsort(points, nCnt, sizeof(points[0]), cmp);bool find ;int index = 0;double wMax = 0;double xleft = 0;int nPoint =0; // 至少需要的点的个数 for(;;) {find = false;wMax = 0;for (int i  = index; i< nCnt; ++i) { // 只有先排序了 才能采用此技巧 if (points[i].l<=xleft) {if (points[i].r-xleft>wMax) {wMax = points[i].r-xleft;index = i;find = true;}} else break;} if (find) {++nPoint;xleft = points[index].r;++index;if (xleft>=l) {cout<<nPoint<<endl;return;}} else {cout<<-1<<endl;return;}}} int main() {int n;double l,w;while (scanf("%d%lf%lf", &n, &l, &w) !=EOF) {int nCur = 0;for (int i =0; i< n; ++i) {double pos, r;scanf("%lf%lf", &pos, &r);if (r<=w/2.0) // 进行预处理 continue;else {double wValied = sqrt(r*r - (w/2.0)*(w/2.0));points[nCur].l = pos - wValied;points[nCur].r = pos + wValied;++nCur;}}solve(nCur, w, l);}return 0;}


0 0
原创粉丝点击