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\n",ans);
    }
    return 0;
}

 

posted @ 2016-07-11 17:44  GFY  阅读(155)  评论(0编辑  收藏  举报