您的位置:首页 > 其它

uva10382解题报告

2015-12-31 12:45 288 查看
题目大意: 在一块宽为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;
else
return 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: