题目链接:http://poj.org/problem?id=1328
--------------------------------------------------------
题意:在平面直角坐标系上,给出多个点。寻找能覆盖的圆的最小个数。
思路:乍一看容易陷入寻找圆的圆心的思路中,然而确定圆心不是一个很容易的事情,其确定方法与其他各点都有一定关系。所以这种思路不可取。然后先从最简单的情况下考虑,如果纵坐标大于圆的半径,那么无论何种方式都不能满足题意,所以输出"-1"。由此获得启发,计算出每个点在y轴上的可行区间,然后判断区间是否有重合的地方。如果重合,圆心可以放置再重合区间内,更新区间,直至每个区间都进行了判断。
注意:1.提交时候出现了CE,注重代码习惯,减少C、C++混合coding方式
2.本题的输入数据注意边界点(半径为0,圆心位于y轴下方),虽然本题测评时没有出现相关数据。
3.本题输入数据类型有可能为double型,样例都为int型,容易产生惯性思维,认为都为int型,要开double。
代码:
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<map> using namespace std; int N =0; int d =0; const int n=1010; double A[n+5];double B[n+5]; double L[n+5];double H[n+5]; int main(void){ int c1 =0; while(scanf("%d%d",&N,&d)){ int flag = 1; if(N==0&&d==0) break; for(int i=0;i<N;i++){ scanf("%lf %lf",&A[i],&B[i]); if(B[i]>d||B[i]<0||d<=0) flag = 0; } for(int j=0;j<N;j++){ L[j]=A[j]-sqrt(double(d*d-B[j]*B[j])); H[j]=A[j]+sqrt(double(d*d-B[j]*B[j])); } int num =1; for(int i=0;i<N;i++){ for(int j=i+1;j<N;j++){ if(L[i]>L[j]){ double tmp =L[i]; L[i]=L[j]; L[j]=tmp; tmp=H[i]; H[i]=H[j]; H[j]=tmp; } } } double ss=L[0]; double st=H[0]; for(int i=1;i<N;i++){ if(L[i]<=st){ if(H[i]<st) st=H[i]; }else{ st=H[i]; num++; } } c1++; if(flag) printf("Case %d: %d\n",c1,num); else printf("Case %d: %d\n",c1,-1); } return 0; }