HDU--1077[Catching Fish] 枚举圆心

来源:互联网 发布:淘宝行业数据分析软件 编辑:程序博客网 时间:2024/05/01 06:39
 题目大意:

给出一些点坐标,问有一个半径为1的圆,一次最多能圈多小个点。

 

思路分析:

(1):一开始想用随机算法(模拟退火)把它水过去得。可是。。。。“火候”一直把握不好,不是WA就是TLE。。。可能这题数据卡的紧,不能用这个方法吧。。。。

(2):第二种思路就是---枚举。应该很容易想的到,枚举任意两个点,把圆心确定下来(本题关键!!),然后遍历所有点,统计在该圆内的点的个数。其中最大值就是答案。。。。。

 

感想:

(1):模拟退火,火候不好掌握(一般不要首选);

(2):实现枚举时发现函数的形参对代码运行速度也有很大影响。形参为point(1250ms)<--->int(656ms)!!!具体见代码。。。

(3):好像用结构体会比较慢,用二维数组会快一点。。。我没有自己实现。。只是对比了下别人的AC代码。。。

 

CODE:形参为point(1250ms)

/*几何题*//*枚举任意两个点,确定圆心,然后遍历所有点统计在该圆内的点的个数*//*AC代码:1250ms*/#include <iostream>#include <cmath>const double eps=1e-6;const int MAXN=305;struct point{double x,y;};struct point ps[MAXN];int N;double get_dis(point a,point b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}void get_center(point a,point b){double ox,oy,dx,dy,r,temp;ox=(a.x+b.x)/2;oy=(a.y+b.y)/2;dx=b.x-a.x;dy=b.y-a.y;ps[N].x=ox;ps[N].y=oy;temp=get_dis(ps[N],b);r=sqrt(1.0-temp);if(fabs(dx)<eps)//竖直的情况ps[N].x-=r;//+或-都可以else{double ang=atan(-dy/dx);ps[N].x-=r*sin(ang);//+或-都可以ps[N].y-=r*cos(ang);}}int main(){int T,i,j,k,max;scanf("%d",&T);while(T--){scanf("%d",&N);for(i=0;i<N;i++)scanf("%lf%lf",&ps[i].x,&ps[i].y);int ans=1;for(i=0;i<N;i++)//枚举O(n^2){for(j=i+1;j<N;j++){if(get_dis(ps[i],ps[j])>=4) continue;get_center(ps[i],ps[j]);for(k=0,max=0;k<N;k++){if(N-k+max<=ans) break;double temp=sqrt(get_dis(ps[k],ps[N]));if(temp<=1.000001)max++;}if(max>ans)ans=max;}}printf("%d\n",ans);}return 0;}


CODE(2):形参为point(656ms)

把两个函数的形参改成int型后即(get_dis(int a,int b)和get_center(int a,int b))时间由1250ms->656ms!!!!

/*几何题*//*枚举任意两个点,确定圆心,然后遍历所有点统计在该圆内的点的个数*//*AC代码:656ms*/#include <iostream>#include <cmath>const double eps=1e-6;const int MAXN=305;struct point{double x,y;};struct point ps[MAXN];int N;double get_dis(int a,int b){return (ps[a].x-ps[b].x)*(ps[a].x-ps[b].x)+(ps[a].y-ps[b].y)*(ps[a].y-ps[b].y);}void get_center(int a,int b){double ox,oy,dx,dy,r,temp;ox=(ps[a].x+ps[b].x)/2;oy=(ps[a].y+ps[b].y)/2;dx=ps[b].x-ps[a].x;dy=ps[b].y-ps[a].y;ps[N].x=ox;ps[N].y=oy;temp=get_dis(N,b);r=sqrt(1.0-temp);if(fabs(dx)<eps)//竖直的情况ps[N].x-=r;//+或-都可以else{double ang=atan(-dy/dx);ps[N].x-=r*sin(ang);//+或-都可以ps[N].y-=r*cos(ang);}}int main(){int T,i,j,k,max;scanf("%d",&T);while(T--){scanf("%d",&N);for(i=0;i<N;i++)scanf("%lf%lf",&ps[i].x,&ps[i].y);int ans=1;for(i=0;i<N;i++)//枚举O(n^2){for(j=i+1;j<N;j++){if(get_dis(i,j)>=4) continue;get_center(i,j);for(k=0,max=0;k<N;k++){if(N-k+max<=ans) break;double temp=sqrt(get_dis(k,N));if(temp<=1.000001)max++;}if(max>ans)ans=max;}}printf("%d\n",ans);}return 0;}


 

CODE(3):模拟退火(WA)、火候张望不好、

/*模拟退火*//*WA*/#include <iostream>#include <cmath>#include <cstdlib>#include <ctime>const int RanN=80;const int RunN=30;const double dp=0.7;const double eps=1e-6;struct px{double x,y;int num;};struct px stu[300+20];struct px S[RanN+10];int N,mans;int get_num(int t){int ans=0;double temp;for(int i=1;i<=N;i++){if(N-i+1+ans<=mans)return 0;temp=sqrt((double)((S[t].x-stu[i].x)*(S[t].x-stu[i].x)+(S[t].y-stu[i].y)*(S[t].y-stu[i].y)));if(temp<=1.000001)//if(temp<1.0001)ans++;}return ans;}void get_ans(){int i,r,max;double delta,k1,k2,tx,ty;mans=1;delta=(double)10.0/(sqrt(1.0*N));for(r=1;r<=RanN;r++){S[r].x=double(rand()*1.0/32767)*10.0;S[r].y=double(rand()*1.0/32767)*10.0;S[r].num=get_num(r);}while(delta>eps){for(r=1;r<=RanN;r++){for(i=1;i<=RunN;i++){k1=double(rand()*1.0/32767)*delta;k2=sqrt(delta*delta-k1*k1);if (rand()%2==1) k1*=-1;//定方向if (rand()%2==1) k2*=-1;tx=S[r].x;ty=S[r].y;S[r].x+=k1;S[r].y+=k2;if(S[r].x>=0&&S[r].x<=10.0&&S[r].y>=0&&S[r].y<=10.0){max=get_num(r);if(max>S[r].num){S[r].num=max;if(max>mans)mans=max;}else{S[r].x=tx;S[r].y=ty;}}}}delta*=dp;}printf("%d\n",mans);}int main(){int T,i;scanf("%d",&T);while(T--){scanf("%d",&N);for(i=1;i<=N;i++)scanf("%lf%lf",&stu[i].x,&stu[i].y);get_ans();}return 0;}
原创粉丝点击