POJ 1981 Circle and Points(单位圆覆盖n^3&&n^2lgn)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove

题目:有一个点集,问一个单位圆最多能覆盖多少个点。

http://poj.org/problem?id=1981

N^3做法。一个覆盖最多点的圆,必然至少有两个点在圆上。当然n>=2而且结果大于2

这样的话,枚举两个点,求出过这两个点的单位圆,然后判断有多少个点在圆中,枚举N^2,判断N,总共是N^3

在POJ ,我的代码4.7S险过

#include<iostream>
#include<fstream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<sstream>
#include<ctime>
#include<cassert>
#define LL long long
#define eps 1e-8
#define inf 999999.0
#define zero(a) abs(a)<eps
#define N 20
#define MOD 100000007
#define pi acos(-1.0)
using namespace std;
struct Point{
    double x,y;
    Point(){}
    Point(double tx,double ty){x=tx;y=ty;}
}p[300];
int n;
double dist(Point p1,Point p2){
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
Point get_circle(Point p1,Point p2){
    Point mid=Point((p1.x+p2.x)/2,(p1.y+p2.y)/2);
    double angle=atan2(p1.x-p2.x,p2.y-p1.y);
    double d=sqrt(1-dist(p1,mid)*dist(p1,mid));
    return Point(mid.x+d*cos(angle),mid.y+d*sin(angle));
}
int main(){
    while(scanf("%d",&n)!=EOF&&n){
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        int ans=1;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(dist(p[i],p[j])>2.0) continue;
                Point central=get_circle(p[i],p[j]);
                int cnt=0;
            //    printf("%.6f %.6f\n",dist(p[i],central),dist(p[j],central));
                for(int k=0;k<n;k++)
                    if(dist(central,p[k])<1.0+eps)
                        cnt++;
                ans=max(ans,cnt);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

N^2lgN做法。以每一个点扩展成单位圆,那么两两之间可能会有相交,形成相交弧。

在这里,只需要判断弧被覆盖多少次即可。因为弧如果被覆盖,那么以弧上的点为圆心,必然也能覆盖到原来点。

做法有点诡异,N^2枚举,求出交点,保存方向以及极角,然后排序,扫描一遍,不是非常理解

有待提高

#include<iostream>
#include<fstream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<sstream>
#include<ctime>
#include<cassert>
#define LL long long
#define eps 1e-8
#define inf 999999.0
#define zero(a) abs(a)<eps
#define N 20
#define MOD 100000007
#define pi acos(-1.0)
using namespace std;
struct Point{
    double x,y;
    Point(){}
    Point(double tx,double ty){x=tx;y=ty;}
}p[300];
struct Node{
    double angle;
    bool in;
}arc[180000];
int n,cnt;
double dist(Point p1,Point p2){
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
bool cmp(Node n1,Node n2){
    return n1.angle!=n2.angle?n1.angle<n2.angle:n1.in>n2.in;
}
void MaxCircleCover(){
    int ans=1;
    for(int i=0;i<n;i++){
        int cnt=0;
        for(int j=0;j<n;j++){
            if(i==j) continue;
            if(dist(p[i],p[j])>2.0) continue;
            double angle=atan2(p[i].y-p[j].y,p[i].x-p[j].x);
            double phi=acos(dist(p[i],p[j])/2);
            arc[cnt].angle=angle-phi;arc[cnt++].in=true;
            arc[cnt].angle=angle+phi;arc[cnt++].in=false;
        }
        sort(arc,arc+cnt,cmp);
        int tmp=1;
        for(int i=0;i<cnt;i++){
            if(arc[i].in)  tmp++;
            else tmp--;
            ans=max(ans,tmp);
        }
    }
    printf("%d\n",ans);
}
int main(){
    while(scanf("%d",&n)!=EOF&&n){
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
            MaxCircleCover();
    }
    return 0;
}





评论 4 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

ACM_cxlove

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值