您的位置:首页 > 其它

2017/3/24 每天都刷刷ACM练练脑子~ 今天刷了一道debug了很久的题...最后发现..哎还是怪自己太马虎

2017-03-24 21:48 375 查看


喷水装置(二)

时间限制:3000 ms  |  内存限制:65535 KB
难度:4

描述有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。

输入第一行输入一个正整数N表示共有n次测试数据。

每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。

随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。

如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5


样例输出
1
2

此题是典型的贪心法 即将每个范围都转化成有效范围 即对应区间上的真实范围(也就是x±根号下r^2-(h/2)^2) 超过了范围的直接记为边界

然后每次都去找当前max中所能延伸的最大区间即贪心思想

#include<iostream>
#include<string>
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
class water
{
public:
double x;
double realR;
double r;
double left;
double right;
};
bool comp(water x, water y)
{
if (x.left != y.left) return x.left < y.left;
else return x.right > y.right;
}
int main()
{
int N, n, sum, i, k; double w, h, x, wetS, max, range;
cin >> N;
while (N--)
{
cin >> n >> w >> h;
sum = 0; wetS = 0;
water *nice = new water
;
for (i = 0; i < n; i++)
{
cin >> nice[i].x >> nice[i].r;
if (nice[i].r <= (h / 2)) { i--; n--; }
else
{
nice[i].realR = sqrt(pow(nice[i].r, 2) - pow(h / 2, 2));
//计算真实范围
nice[i].left = nice[i].x - nice[i].realR; if (nice[i].left < 0) nice[i].left = 0;
nice[i].right = nice[i].x + nice[i].realR; if (nice[i].right>w) nice[i].right = w;
//超过了边界的直接记为边界
}
}
sort(nice, nice + n, comp);//这个排序很好用

max = 0; range = 0;

//如果第一个点未能覆盖到0处 肯定是不能浇灌完所有的区间
if (nice[0].left != 0);
else
{
//max就是当前所能找到覆盖最大的区间
while (max < w)
{
range = max;
for (i = 0; i < n&&nice[i].left<=max; i++)
{
if (nice[i].right>range) { range = nice[i].right; }
//不断的去延伸 要是循环结束后range未变 即延伸出现了断点 所以就直接宣布失败
}
if (max != range) { max = range; sum++; if (max == w) { break; } }
else { sum = 0; break; }
}
}
cout << sum << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐