zoukankan      html  css  js  c++  java
  • POJ

    题意:给定N个点,然后给定一个半径为R的圆,问这个圆最多覆盖多少个点。

    思路:在圆弧上求扫描线。

    如果N比较小,不难想到N^3的算法。 一般这种覆盖问题你可以假设有两个点在圆的边界上,那么每次产生的圆去看多少个点在园内即可。

    但是我们现在要更高效的做法。题目等价于,有N个半径为R的圆,问二维平面上一点最多被多少个圆覆盖。即我们可以每次求交,交的部分标记++;

    hihocoder1508的代码。

    #include<bits/stdc++.h>
    #define pdd pair<double,int>
    #define f first
    #define s second
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=200010;
    const double eps=1e-12;
    const double pi=acos(-1.0);
    struct point{ double x,y;}p[maxn];
    double det(point a,point b){ return a.x*b.y-a.y*b.x;}
    double dot(point a,point b){ return a.x*b.x+a.y*b.y;}
    point operator +(point a,point b){ return point{a.x+b.x,a.y+b.y}; }
    point operator -(point a,point b){ return point{a.x-b.x,a.y-b.y}; }
    double dist(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    int dcmp(double x){ if(fabs(x)<eps) return 0; return x>0?1:-1;}
    pdd a[maxn]; int ans,N; double ang1,ang2,R;
    void CirinterCir(point a,point b)
    {
        double L=dist(a,b)/2,t=acos(L/R);
        double base=atan2(b.y-a.y,b.x-a.x);
        ang1=base+t,ang2=base-t;
    }
    bool check(point i,point j)
    {
        double ang=(ang1+ang2)/2;
        point x=point{i.x+R*cos(ang),i.y+R*sin(ang)};
        return dcmp(dist(x,j)-R)<=0;
    }
    void solve()
    {
        rep(i,1,N) {
            int cnt=1,Mx,tot=0;
            rep(j,1,N) {
                if(i==j||dist(p[i],p[j])>R+R) continue;
                if(p[i].x==p[j].x&&p[i].y==p[j].y) { cnt++; continue;}
                CirinterCir(p[i],p[j]);
                if(ang1>ang2) swap(ang1,ang2);
                if(check(p[i],p[j])){
                    a[++tot]=pdd(ang1-eps,-1);
                    a[++tot]=pdd(ang2,0);
                }
                else {
                    a[+tot]=pdd(-pi-eps,-1);
                    a[++tot]=pdd(ang1,0);
                    a[++tot]=pdd(ang2-eps,-1);
                    a[++tot]=pdd(pi,0);
                }
            }
            sort(a+1,a+tot+1); Mx=cnt;
            rep(i,1,tot){
                if(a[i].s==-1) cnt++;
                else cnt--;
                Mx=max(Mx,cnt);
            }
            ans=max(ans,Mx);
        }
    }
    int main()
    {
        scanf("%d%lf",&N,&R);
        rep(i,1,N) scanf("%lf%lf",&p[i].x,&p[i].y);
        solve();
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Java命令行启动jar包更改默认端口以及配置文件的几种方式
    Windows下带配置文件的mysql命令行安装方法
    Windows下mysql主从搭建
    Windows下mysql集群搭建
    CAP原则(CAP定理)、BASE理论(精简)
    进程间通讯的7种方式
    Go Web 编程之 数据库
    Go 每日一库之 fsnotify
    Go 每日一库之 viper
    Go 每日一库之 go-ini
  • 原文地址:https://www.cnblogs.com/hua-dong/p/11479910.html
Copyright © 2011-2022 走看看