题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=85904#problem/E
题意:
有n个喷头安装在长l米宽w米长的水平草条中间的水平线上,给出每个喷头的半径。为了让水平草条都浇到水,最少需要多少喷头?如果没办法完全浇到水平草条。输出-1。
案例:
input
3 10 1
3 5
9 3
6 1
3 10 1
5 3
1 1
9 1
output
2
-1
思路分析:
当喷头的射程半径小于等于水平草条的宽度的一半,不能完全覆盖草坪,可以直接忽视这样的点,而另外的可以通过加减sqrt(r*r-w*w)得出喷头范围的左右端点,就成了一个区间覆盖问题,与MINIMAL COVERAGE的思路是一样的。不懂的人可以参考那题。
源代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 using namespace std; 6 double a[2][10010],b[10010]; 7 int n,count,j; 8 double l,w; 9 void search(double le) //区间覆盖 10 { 11 for(int i=0;i<j;i++) 12 if(a[0][i]<=le&&a[1][i]>le&&a[1][i]>b[count]) 13 b[count]=a[1][i]; 14 if(b[count]!=0&&b[count]<l) 15 { 16 count++; 17 search(b[count-1]); 18 } 19 } 20 int main() 21 { 22 while(scanf("%d%lf%lf",&n,&l,&w)!=EOF) 23 { 24 double o,r,nr; //必须用double 25 j=0; 26 count=0; 27 memset(b,0,sizeof(b)); 28 for(int i=0;i<n;i++) 29 { 30 scanf("%lf%lf",&o,&r); 31 if(r<=w/2.0) continue; //不需考虑的情况 32 nr=sqrt(r*r-w*w/4.0); //预处理 33 a[0][j]=o-nr; 34 a[1][j]=o+nr; 35 j++; 36 } 37 search(0); 38 if(b[count]<l) 39 printf("-1\n"); 40 else 41 printf("%d\n",count+1); 42 } 43 return 0; 44 }