zoukankan      html  css  js  c++  java
  • HDU 4116 Fruit Ninja

    http://acm.hdu.edu.cn/showproblem.php?pid=4116

    题意:给N个圆,求一条直线最多能经过几个圆?(相切也算)

    思路:枚举中心圆,将其他圆的切线按照极角排序,并赋上权值(1-1),那么我们for一遍,sum随时加上权值,当sum最大时,就可以更新答案。

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    const double eps=1e-9;
    const double Pi=acos(-1);
    int n;
    struct Point{
        double x,y,r;
        Point(){}
        Point(double x0,double y0,double r0):x(x0),y(y0),r(r0){}    
        Point(double x0,double y0):x(x0),y(y0){}
    }p[800005];
    bool vis[800005];
    struct Line{
        int id,c;
        double ang;
        Line(){}
        Line(int id0,int c0,double ang0):id(id0),c(c0),ang(ang0){}
    }L[800005];
    int sgn(double x){
        if (x>eps) return 1;
        if (x<-eps) return -1;
        return 0;
    }
    double fix(double x){
        while (sgn(x)<0) x+=2.0*Pi;
        while (sgn(x-Pi-Pi)>=0) x-=2.0*Pi;
        return x;
    }
    bool cmp(Line p1,Line p2){
        int tmp=sgn(p1.ang-p2.ang);
        if (tmp) return tmp<0;
        else return p1.c>p2.c;
    }
    int read(){
        int t=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
        while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
        return t*f;
    }
    Point operator -(Point p1,Point p2){
        return Point(p1.x-p2.x,p1.y-p2.y,0);
    }
    double sqr(double x){
        return x*x;
    }
    double dist(Point p){
        return sqrt(sqr(p.x)+sqr(p.y));
    }
    double dist(Point p1,Point p2){
        return dist(p1-p2);
    }
    Point getPoint(Point p,double ang){
        return Point(p.x+cos(ang)*p.r,p.y+sin(ang)*p.r);
    }
    void cut_line(Point &A,Point &B,int &id,int &sum,int &len){
        double dis=dist(A,B);
        double Base=atan2(B.y-A.y,B.x-A.x);
        if (sgn(A.r-B.r-dis)>0) return;
        if (sgn(B.r-A.r-dis)>=0){
            sum++;return;
        }
        double ang1=asin((B.r-A.r)/dis);
        double ang2=asin((B.r+A.r)/dis);
        if (sgn(A.r+B.r-dis)>=0){
            L[++len]=Line(id,1,fix(Base-ang1));
            L[++len]=Line(id,-1,fix(Base+ang1+Pi));
            return;
        }
        L[++len]=Line(id,1,fix(Base-ang1));
        L[++len]=Line(id,-1,fix(Base+ang1+Pi));
        L[++len]=Line(id,-1,fix(Base+ang2));
        L[++len]=Line(id,1,fix(Base-ang2+Pi));
        return;    
    }
    int work(int n,int len){
        int res=0;
        int sum=0;
        memset(vis,false,sizeof(bool)*(n+4));
        for (int i=1;i<=(len<<1);i++){
            int k=(i>len)?i-len:i;
            int id=L[k].id;
            int c=L[k].c;
            if (c==1){
                if (!vis[id]){
                    vis[id]=true;
                    sum++;
                }
            }else{
                if (vis[id]){
                    vis[id]=false;
                    sum--;
                }
            }
            if (sum>res) res=sum;
        }
        return res;
    }
    int main(){
        int T=read(),Tcase=0;
        while (T--){
            n=read();printf("Case #%d: ",++Tcase);
            for (int i=1;i<=n;i++)
             scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].r);
            int ans=0;
            for (int i=1;i<=n;i++){
                int len=0;int sum=1;
                for (int j=1;j<=n;j++) if (i!=j)
                 cut_line(p[i],p[j],j,sum,len);
                std::sort(L+1,L+1+len,cmp);
                sum+=work(n,len);
                ans=std::max(ans,sum);
            } 
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    SQL SELECT INTO 语句
    跨站脚本攻击测试[转]
    Visual Studio 2008中如何比较二个数据库的架构【Schema】和数据【Data】并同步 [转贴]
    联表UPDATE
    网站架构策划方案
    概念模型 逻辑模型 物理模型 区别
    Repeater嵌套绑定Repeater
    .net 2.0升级到了.net 3.5,开发工具从vs2005转为vs2008
    你必须知道的C#的25个基础概念(附演示) 【转】
    window2003中,在IIS中,如何解决不能播放.FLV文件
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5661095.html
Copyright © 2011-2022 走看看