简单几何+并查集 —— 2015NAQ K

问题可以简化成, 最大能取到多少,使得前 个圆不能使左边界和右边界联通。
并查集维护圆与圆、圆与左右边界的联通性即可。
#include<bits/stdc++.h>
using namespace std;
#define N 505
typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){
    if (k>eps) return 1; else if (k<-eps) return -1; return 0;
}
int cmp(db k1,db k2){return sign(k1-k2);}
int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内 
struct point{
    db x,y;
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    point operator * (db k1) const{return (point){x*k1,y*k1};}
    point operator / (db k1) const{return (point){x/k1,y/k1};}
    point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
    point turn90(){return (point){-y,x};}
    db abs(){return sqrt(x*x+y*y);}
    db abs2(){return x*x+y*y;}
    db dis(point k1){return ((*this)-k1).abs();}
    point unit(){db w=abs(); return (point){x/w,y/w};}
};
int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
db rad(point k1,point k2){return atan2(cross(k1,k2),dot(k1,k2));}
struct circle{
    point o; db r;
    int inside(point k){return cmp(r,o.dis(k));}
};

int n;
circle c[N];
point k1,k2,k3,k4;


int F[N];
int find(int x){
    return x==F[x]?x:F[x]=find(F[x]);
}
void bing(int u,int v){
    int fu=find(u),fv=find(v);
    if(fu!=fv)
        F[fu]=fv;
}
int judge(int n){
    for(int i=1;i<=n+2;i++)F[i]=i;
    for(int i=1;i<=n;i++){
        if(c[i].o.x<c[i].r)bing(i,n+1);//圆和左边界相交
        if(c[i].o.x+c[i].r>200)bing(i,n+2);//圆和右边界相交
        for(int j=i+1;j<=n;j++)
            if(c[i].r+c[j].r>c[i].o.dis(c[j].o)) 
                bing(i,j); 
    }
    if(find(n+1)==find(n+2))
        return 0;
    return 1; 
}
int main(){
    k1=(point){0.0,0.0};
    k2=(point){200.0,0.0};
    k3=(point){200.0,300.0};
    k4=(point){0,300.0};
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%lf%lf%lf",&c[i].o.x,&c[i].o.y,&c[i].r);
    int ans=0;
    for(int i=1;i<=n;i++){
        if(judge(i))ans=i;
        else break;
    }
    cout<<ans<<'\n';
} 

 

posted on 2020-04-19 21:54  zsben  阅读(151)  评论(0编辑  收藏  举报

导航