zoukankan      html  css  js  c++  java
  • Asia Jakarta Regional Contest 2019 I

    cf的地址
    因为校强, "咕咕十段"队获得了EC-final的参赛资格
    因为我弱, "咕咕十段"队现在银面很大
    于是咕咕十段决定进行训练. 周末vp了一场, 这是赛后补题.
    vp的时候想到了可以利用边界和切线, 但是没有仔细思考.
    后来发现, 找到可以走的边界和切线之后, bfs一下就完事了啊.
    题目给的eps限制使得我们可以合法的沿着切线和边界进行行走
    关键在于找出"可以走的边界和切线"
    如果一条切线在两个切点之间穿过了一个圆, 那么就不走这条切线(肯定可以走中间那个圆的某几条切线)
    一条切线可以向两个切点外侧延伸, 直到与某个圆/边界相交.
    主要麻烦的地方在于找圆的切线以及内外公切线. 以及我现在竟然能把直线求交写错...

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const double eps = 1e-7;
    struct point{
        double x, y;
        point(double a = 0.0, double b = 0.0):x(a), y(b){}
        point operator - (const point &A)const{
            return point(x-A.x, y-A.y);
        }
        point operator + (const point &A)const{
            return point(x+A.x, y+A.y);
        }
        void read(){
            scanf("%lf%lf",&x,&y);
        }
        point rot(double theta)const{
            return point(x*cos(theta)-y*sin(theta), x*sin(theta) + y*cos(theta));
        }
        double length()const{
            return sqrt(x*x+y*y);
        }
        point norm()const {
            return point(x/length(), y/length());
        }
        void output(){
            printf("%lf %lf",x,y);
        }
    }pL, pR, S, T, C[52];
    double r[52];
    double cross(const point &A, const point &B){
        return A.x * B.y -A.y * B.x;
    }
    struct Line{
        point S, dlt;
        double tmax, tmin;
        Line(){
            tmax = 1e20;
            tmin = -1e20;
        }
        Line(point s, point t){
            S = s;
            dlt = t - s;
            tmax = 1e20;
            tmin = -1e20;
        }
        Line(point s, point t, double t1, double t2){
            S = s; dlt = t - s;
            tmin = t1; tmax = t2;
        }
        point operator () (const double &t)const{
            return S + point(dlt.x*t, dlt.y*t);
        }
        bool through(const point &p)const {
            return fabs(cross(p-S, dlt))<eps;
        }
        double gett(const point &p)const{
            if(fabs(p.x - S.x) > eps){
                return (p.x - S.x)/(dlt.x);
            }else if(fabs(p.y - S.y)>eps){
                return (p.y - S.y)/(dlt.y);
            }else{
                return 0;
            }
        }
        bool contain(const point &p)const{
            if(fabs(cross(p-S, dlt))>eps)return false;
            double t = gett(p);
            return t>=tmin-eps&&t<=tmax+eps;
        }
        point getp(double t)const{
            return point(S.x+t*dlt.x, S.y+t*dlt.y);
        }
        void output(){
            S.output();(S+dlt).output();
        }
    }L[6000];
    Line tangent(point P, point C, double r, int flag){
        double theta = acos(r/(P-C).length());
        point v = (P-C).norm();
        v = point(v.x*r, v.y*r);
        v = v.rot(flag*theta);
        point T = C + v;
        return Line(P, T);
    }
    Line tangent_out(point C1, double r1, point C2, double r2, int flag){
        if((fabs(r1-r2))<eps){
            point v = (C1-C2).norm();
            v = point(v.x * r1, v.y * r1);
            v = v.rot(flag*acos(-1)/2);
            return Line(C1+v, C2+v);
        }else{
            if(r1>r2){
                swap(C1, C2);
                swap(r1, r2);
            }
            //r1<r2
            //r1/r2 = (l1)/(l2), l2-l1 = length(C1-C2)
            double L = (C1 - C2).length();
            L = L * r2/(r2-r1);
            point v = (C1-C2).norm();
            double theta = flag * acos(r2/L);
            v = v.rot(theta);
            return Line(C1 + point(v.x*r1, v.y*r1), C2 + point(v.x*r2, v.y*r2));
        }
    }
    Line tangent_in(point C1, double r1, point C2, double r2, int flag){
        point v = (C2 - C1);
        point P = C1 + point(v.x*r1/(r1+r2), v.y*r1/(r1+r2));
        double theta = flag*acos(r1/(P-C1).length());
        v = v.norm().rot(theta);
        return Line(C1 + point(v.x*r1, v.y*r1), C2 - point(v.x*r2,v.y*r2));
    }
    int cnt_lines = 0, cnt_lines2 = 0;
    point intersect(const Line &L1, const Line &L2){
        double C = cross(L1.dlt, L2.dlt);
        if(fabs(C)<eps)return point(1e20, 1e20); 
        else{
            double t = cross(L1.S - L2.S, L2.dlt)/cross(L2.dlt, L1.dlt);
            return L1(t); 
        }
    }
    double mult(const point &P1, const point &P2){
        return P1.x*P2.x + P1.y*P2.y;
    }
    bool between(point P, Line &L){
        point S = L.S, T = L.S + L.dlt;
        return mult(S-P, T-P) < -eps;
    }
    bool intersect(Line &L, point C, double r){
        double dis = fabs(cross(C-L.S, L.dlt))/L.dlt.length();
        if(dis > r - eps)return false;
        double theta = acos(dis/r);
        int flag = cross(C-L.S, L.dlt) > eps ? (1) : (-1);
        point v = L.dlt.norm().rot(flag * acos(-1)/2 + theta);
        point p = C + point(v.x*r, v.y*r);
        if(between(p, L)){
            return true;
        }else{
            double t = L.gett(p);
            if(t < 0 && t > L.tmin){
                L.tmin = t;
            }
            if(t > 0 && t < L.tmax){
                L.tmax = t;
            }
            v = L.dlt.norm().rot(flag * acos(-1)/2 - theta);
            p = C + point(v.x*r, v.y*r);
            t = L.gett(p);
            if(t < 0 && t > L.tmin){
                L.tmin = t;
            }
            if(t > 0 && t < L.tmax){
                L.tmax = t;
            }
            return false;
        }
    }
    int N;
    bool visited[6000];
    int pre[6000], dis[6000];
    int q[6000];
    void output(int x, int cnt){
        if(pre[x] == 0){
            printf("%d
    ",cnt);
        }else{
            output(pre[x], cnt+1);
            point p = intersect(L[x], L[pre[x]]);
            p.output();printf("
    ");
        }
    }
    void bfs(){
        int head = 0, tail = 0;
        visited[0] = true; dis[0] = 0;//S
        for(int i = 1; i <= cnt_lines2; ++i){
            if(L[i].contain(S)){
                pre[i] = 0; dis[i] = 1;
                visited[i] = true;
                q[tail++] = i;
            }
        }
        while(head!=tail){
            int x = q[head++];
            if(L[x].contain(T)){
                output(x, 0);
                break;
            }else{
                for(int i=1;i<=cnt_lines2;++i){
                    if(!visited[i]){
                        point p = intersect(L[i],L[x]);
                        if(L[i].contain(p)&&L[x].contain(p)){
                            q[tail++] = i;
                            visited[i] = true;
                            pre[i] = x;
                            dis[i] = dis[x] + 1;
                        }
                    }
                }
            }
        }
    }
    int main(){
        scanf("%d",&N);
        pL.read();pR.read();
        S.read();T.read();
        for(int i = 1;i <= N;++i){
            C[i].read();scanf("%lf", r+i);
        }
        L[++cnt_lines] = Line(S, T);
        for(int i = 1;i <= N;++i){
            L[++cnt_lines] = tangent(S, C[i], r[i], 1);
            L[++cnt_lines] = tangent(S, C[i], r[i], -1);
            L[++cnt_lines] = tangent(T, C[i], r[i], 1);
            L[++cnt_lines] = tangent(T, C[i], r[i], -1);
        }
        for(int i = 1;i <= N;++i){
            for(int j = i + 1;j <= N;++j){
                L[++cnt_lines] = tangent_out(C[i], r[i], C[j], r[j], 1);
                L[++cnt_lines] = tangent_out(C[i], r[i], C[j], r[j],-1);
                L[++cnt_lines] = tangent_in(C[i], r[i], C[j], r[j], 1);
                L[++cnt_lines] = tangent_in(C[i], r[i], C[j], r[j],-1);
            }
        }
        for(int i=1;i<=cnt_lines;++i){
            bool flag = true;
            for(int j = 1;j <= N;++j){
                if(intersect(L[i], C[j], r[j])){
                    flag = false;break;
                }
            }
            if(flag){
                L[++cnt_lines2] = L[i];
            }
        }
        L[++cnt_lines2] = Line(point(pL.x, pL.y), point(pL.x, pR.y), 0, 1);
        L[++cnt_lines2] = Line(point(pR.x, pL.y), point(pR.x, pR.y), 0, 1);
        L[++cnt_lines2] = Line(point(pL.x, pL.y), point(pR.x, pL.y), 0, 1);
        L[++cnt_lines2] = Line(point(pL.x, pR.y), point(pR.x, pR.y), 0, 1);
        for(int i=1;i<=cnt_lines2 - 4;++i){
            for(int j=cnt_lines2 - 3;j<=cnt_lines2;++j){
                point p = intersect(L[i], L[j]);
                double t = L[i].gett(p);
                if(t<0&&t>L[i].tmin){
                    L[i].tmin = t;
                }
                if(t>0&&t<L[i].tmax){
                    L[i].tmax = t;
                }
            }
        }
        bfs();
        return 0;
    }
    
  • 相关阅读:
    浅谈IO这件事
    tushare+pandas实现财经数据分析
    大话设计模式Python实现-解释器模式
    大话设计模式Python实现- 享元模式
    大话设计模式Python实现-中介者模式
    大话设计模式Python实现-职责链模式
    大话设计模式Python实现-命令模式
    大话设计模式Python实现-桥接模式
    java之AbstractStringBuilder类详解
    java之Class类详解
  • 原文地址:https://www.cnblogs.com/liu-runda/p/11941410.html
Copyright © 2011-2022 走看看