喷水装置(二)
时间限制:
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
-
第一行输入一个正整数N表示共有n次测试数据。
个人感受
这道题当时卡了我也是半天,非常无奈,主要思路就是贪心策略,把它的每一个的覆盖开始坐标和结束坐标都算一下,然后让能覆盖的长区间覆盖上去,如果中间有断档,则GG,上代码。
01.
#include <stdio.h>
02.
#include <string.h>
03.
#include <algorithm>
04.
#include <math.h>
05.
struct
keer
06.
{
07.
int
a,b;
08.
double
c,d;//c,d分别是1个喷水装置的开始和结束的坐标
09.
} s[10005];
10.
int
f(keer x, keer y)//进行排序定义
11.
{
12.
if
(x.c==y.c)
13.
return
x.d>y.d;
14.
return
x.c<y.c;
15.
}
16.
using
namespace
std;
17.
int
main()
18.
{
19.
int
t;
20.
scanf
(
"%d"
,&t);
21.
while
(t--)
22.
{
23.
int
n;
24.
double
x,y;
25.
scanf
(
"%d%lf%lf"
,&n,&x,&y);
26.
for
(
int
i=0; i<n; i++)
27.
{
28.
scanf
(
"%d%d"
,&s[i].a,&s[i].b);
29.
s[i].c=s[i].a-
sqrt
(s[i].b*s[i].b-y*y/4.0);//计算开始的坐标
30.
s[i].d=s[i].a+
sqrt
(s[i].b*s[i].b-y*y/4.0);//计算结束的坐标
31.
}
32.
sort(s,s+n,f);
33.
int
tt=0;
34.
int
o=0;
35.
double
endd=0;
36.
while
(endd<x)
37.
{
38.
double
opq=endd;
39.
for
(
int
i=0; i<n; i++)
40.
{
41.
if
(opq>=s[i].c&&s[i].d>endd)//为使它能够完全覆盖,进行判断
42.
{
43.
endd=s[i].d;
44.
}
45.
}
46.
if
(opq==endd)//如果发现覆盖晚之后和上次的相同说明没有覆盖,输出0;
47.
{
48.
tt=1;
49.
break
;
50.
}
51.
else
52.
{
53.
o++;
54.
}
55.
}
56.
if
(tt)
57.
printf
(
"0\n"
);
58.
else
59.
printf
(
"%d\n"
,o);
60.
}
61.
return
0;
62.
}