[zoj]3575 Under Attack III
题目大意:
给出一个椭圆和平面上的一些点,求椭圆最多覆盖的点数。其中椭圆长短轴方向固定不可旋转。
思路:
首先将图的横纵坐标乘上一定系数使椭圆覆盖问题变为圆覆盖问题。可以很容易地证明,一定存在一个最优解使得圆周上存在两个或两个以上地点。
由于圆的半径一定,所以枚举圆周上的两个点,可算出圆的位置(可能有两个不同的圆),再求出覆盖点数并取最优解。
#include <stdio.h> #include "stdlib.h" #include "math.h" double dis(double x1,double y1,double x2,double y2){ return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); } long try(double p[210][2],long n,double xo,double yo,double r){ double d; long i,re; re=0; for (i=0;i<n;i++){ d=dis(p[i][0], p[i][1], xo, yo); if ((d-r)<0.0001){ re+=1; } } return re; } int main (){ double p[210][2],a,b,x,y,x1,y1,x2,y2,xp,yp,r,d,an,pi,xo,yo; long i,j,k,n,max,te; pi=asin(1); while (scanf("%lf%lf",&a,&b)!=EOF){ a=a*2; b=b*2; scanf("%ld",&n); for (i=0;i<n;i++){ scanf("%lf%lf",p[i],p[i]+1); p[i][1]*=(a/b); } r=a/2; max=0; for (i=0;i<n;i++){ for (j=i+1;j<n;j++){ d=dis(p[i][0],p[i][1],p[j][0],p[j][1]); if (d>a) continue; xp=sqrt(r*r-d*d/4); an=atan((p[j][1]-p[i][1])/(p[j][0]-p[i][0]))-pi; yp=xp*sin(an); xp=xp*cos(an); xo=(p[i][0]+p[j][0])/2; yo=(p[i][1]+p[j][1])/2; te=try(p,n,xo+xp,yo+yp,r); if (te>max) max=te; te=try(p,n,xo-xp,yo-yp,r); if (te>max) max=te; } } if (max==0) max=1; printf("%ld\n",max); } return 0; }