[代码]ural 1913 Titan Ruins: Old Generators

系统 1782 0

Abstract

ural 1913 Titan Ruins: Old Generators Are Fine Too

implementation 几何 圆交

Source

http://acm.timus.ru/problem.aspx?space=1&num=1913

Solution

主要思路就是判断距离到某两个点是r,另一个点是2r的点。

比赛时候用三分乱搞,大概是被卡了精度还是什么的,没有通过。

赛后用圆交重写了一遍,一开始还是没通过。

然后发现自己的圆交模板是针对面积问题的,单点的情况没有考虑清楚,乱改的时候改错了。大致就是 处理圆覆盖的情况时,在预处理统计时算被覆盖了一次,在算两圆交点的时候又被统计了一次 。还是没弄熟悉圆交的原理所致。

Code

      #include <iostream>
      
        

#include 
      
      <cassert>
      
        

#include 
      
      <cmath>
      
        

#include 
      
      <cstdio>
      
        

#include 
      
      <cstring>
      
        

#include 
      
      <algorithm>


      
        using
      
      
        namespace
      
      
         std;




      
      
        const
      
      
        double
      
       EPS = 1e-
      
        8
      
      
        ;


      
      
        const
      
      
        double
      
       PI = acos(-
      
        1.0
      
      
        );



inline 
      
      
        int
      
       sgn(
      
        double
      
      
         x) {

    
      
      
        if
      
       (fabs(x)<EPS) 
      
        return
      
      
        0
      
      
        ;

    
      
      
        return
      
       x>
      
        0
      
      ?
      
        1
      
      :-
      
        1
      
      
        ;

}




      
      
        struct
      
      
         sp {

    
      
      
        double
      
      
         x, y;

    
      
      
        double
      
      
         pa;

    
      
      
        int
      
      
         cnt;

    sp() {}

    sp(
      
      
        double
      
       a, 
      
        double
      
      
         b): x(a), y(b) {}

    sp(
      
      
        double
      
       a, 
      
        double
      
       b, 
      
        double
      
       c, 
      
        int
      
      
         d): x(a), y(b), pa(c), cnt(d) {}

    
      
      
        bool
      
      
        operator
      
      <(
      
        const
      
       sp &rhs) 
      
        const
      
      
         {

        
      
      
        if
      
       (sgn(pa-rhs.pa)==
      
        0
      
      ) 
      
        return
      
       cnt>
      
        rhs.cnt;

        
      
      
        return
      
       pa<
      
        rhs.pa;

    }

    
      
      
        void
      
       read() {scanf(
      
        "
      
      
        %lf%lf
      
      
        "
      
      , &x, &
      
        y);}

    
      
      
        void
      
       write() {printf(
      
        "
      
      
        %.10f %.10f\n
      
      
        "
      
      
        , x, y);}

}t, s1, s2, p[
      
      
        5
      
      ], e[
      
        20
      
      
        ];


      
      
        double
      
       r, rad[
      
        5
      
      
        ];


      
      
        int
      
       cover[
      
        5
      
      
        ];



sp 
      
      
        operator
      
      *(
      
        double
      
       d, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       sp(d*v.x, d*
      
        v.y);

}



sp 
      
      
        operator
      
      -(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       sp(u.x-v.x, u.y-
      
        v.y);

}



sp 
      
      
        operator
      
      +(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       sp(u.x+v.x, u.y+
      
        v.y);

}




      
      
        double
      
       dot(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       u.x*v.x+u.y*
      
        v.y;

}




      
      
        double
      
       det(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       u.x*v.y-u.y*
      
        v.x;

}




      
      
        double
      
       dis(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        double
      
       dx = u.x-
      
        v.x;

    
      
      
        double
      
       dy = u.y-
      
        v.y;

    
      
      
        return
      
       sqrt(dx*dx+dy*
      
        dy);

}




      
      
        double
      
       dissqr(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        double
      
       dx = u.x-
      
        v.x;

    
      
      
        double
      
       dy = u.y-
      
        v.y;

    
      
      
        return
      
       dx*dx+dy*
      
        dy;

}




      
      
        void
      
      
         write(sp u, sp v) {

    puts(
      
      
        "
      
      
        Now we have enough power
      
      
        "
      
      
        );

    u.write(); v.write();

}




      
      
        bool
      
       cirint(
      
        const
      
       sp &u, 
      
        double
      
       ru, 
      
        const
      
       sp &v, 
      
        double
      
       rv, sp &a, sp &
      
        b) {

    
      
      
        double
      
       d =
      
         dis(u, v);

    
      
      
        if
      
       (sgn(d-(ru+rv))>
      
        0
      
       || sgn(d-fabs(ru-rv))<=
      
        0
      
      ) 
      
        return
      
      
        0
      
      
        ;

    sp c 
      
      = u-
      
        v;

    
      
      
        double
      
      
         ca, sa, cb, sb, csum, ssum;



    ca 
      
      = c.x/d, sa = c.y/
      
        d;

    cb 
      
      = (rv*rv+d*d-ru*ru)/(
      
        2
      
      *rv*d), sb = sqrt(
      
        1
      
      -cb*
      
        cb);

    csum 
      
      = ca*cb-sa*
      
        sb;

    ssum 
      
      = sa*cb+sb*
      
        ca;

    a 
      
      = sp(rv*csum, rv*
      
        ssum);

    a 
      
      = a+
      
        v;



    sb 
      
      = -
      
        sb;

    csum 
      
      = ca*cb-sa*
      
        sb;

    ssum 
      
      = sa*cb+sb*
      
        ca;

    b 
      
      = sp(rv*csum, rv*
      
        ssum);

    b 
      
      = b+
      
        v;



    
      
      
        return
      
      
        1
      
      
        ;

}




      
      
        bool
      
       cu(
      
        int
      
       N, sp p[], 
      
        double
      
       r[], sp &
      
        res) {

    
      
      
        int
      
      
         i, j, k;

    memset(cover, 
      
      
        0
      
      , 
      
        sizeof
      
      
         cover);

    
      
      
        for
      
       (i = 
      
        0
      
      ; i < N; ++
      
        i)

        
      
      
        for
      
       (j = 
      
        0
      
      ; j < N; ++
      
        j) {

            
      
      
        double
      
       rd = r[i]-
      
        r[j];

            
      
      
        if
      
       (i!=j && sgn(rd)>
      
        0
      
       && sgn(dis(p[i], p[j])-rd)<=
      
        0
      
      
        )

                cover[j]
      
      ++
      
        ;

        }

    sp a, b;

    
      
      
        for
      
       (i = 
      
        0
      
      ; i < N; ++
      
        i) {

        
      
      
        int
      
       ecnt = 
      
        0
      
      
        ;

        e[ecnt
      
      ++] = sp(p[i].x-r[i], p[i].y, -PI, 
      
        1
      
      
        );

        e[ecnt
      
      ++] = sp(p[i].x-r[i], p[i].y, PI, -
      
        1
      
      
        );

        
      
      
        for
      
       (j = 
      
        0
      
      ; j < N; ++
      
        j) {

            
      
      
        if
      
       (j==i) 
      
        continue
      
      
        ;

            
      
      
        if
      
      
         (cirint(p[i], r[i], p[j], r[j], a, b)) {

                e[ecnt
      
      ++] = sp(a.x, a.y, atan2(a.y-p[i].y, a.x-p[i].x), 
      
        1
      
      
        );

                e[ecnt
      
      ++] = sp(b.x, b.y, atan2(b.y-p[i].y, b.x-p[i].x), -
      
        1
      
      
        );

                
      
      
        if
      
       (sgn(e[ecnt-
      
        2
      
      ].pa-e[ecnt-
      
        1
      
      ].pa)>
      
        0
      
      
        ) {

                    e[
      
      
        0
      
      ].cnt++
      
        ;

                    e[
      
      
        1
      
      ].cnt--
      
        ;

                }

            }

        }

        sort(e, e
      
      +
      
        ecnt);

        
      
      
        int
      
       cnt = e[
      
        0
      
      
        ].cnt;

        
      
      
        for
      
       (j = 
      
        1
      
      ; j < ecnt; ++
      
        j) {

            
      
      
        if
      
       (cover[i]+cnt==
      
        N) {

                
      
      
        double
      
       a = (e[j].pa+e[j-
      
        1
      
      ].pa)/
      
        2
      
      
        ;

                res 
      
      = p[i]+sp(r[i]*cos(a), r[i]*
      
        sin(a));

                
      
      
        return
      
      
        1
      
      
        ;

            }

            cnt 
      
      +=
      
         e[j].cnt;

        }

    }

    
      
      
        return
      
      
        0
      
      
        ;

}




      
      
        bool
      
       solve(
      
        const
      
       sp &o, 
      
        const
      
       sp &u, 
      
        const
      
       sp &v, 
      
        double
      
      
         r) {

    p[
      
      
        0
      
      ] = o, rad[
      
        0
      
      ] = r+
      
        r;

    p[
      
      
        1
      
      ] = u; p[
      
        2
      
      ] = v; rad[
      
        1
      
      ] = rad[
      
        2
      
      ] =
      
         r;

    sp a, b;

    
      
      
        if
      
       (cu(
      
        3
      
      
        , p, rad, a)) {

        b 
      
      = 
      
        0.5
      
      *(a-
      
        o);

        b 
      
      = o+
      
        b;

        write(a, b);

        
      
      
        return
      
      
        1
      
      
        ;

    }

    
      
      
        else
      
      
        return
      
      
        0
      
      
        ;

}




      
      
        int
      
      
         main() {

    cin
      
      >>
      
        r;

    t.read(); s1.read(); s2.read();

    sp a, b, c, d;

    
      
      
        if
      
      
         (cirint(s1, r, s2, r, a, b)) {

        
      
      
        if
      
       (solve(t, s1, s2, r)) 
      
        return
      
      
        0
      
      
        ;

    }

    
      
      
        else
      
      
         {

        
      
      
        if
      
       (cirint(s1, r, t, r, a, b) &&
      
         cirint(s2, r, t, r, c, d)) {

            write(a, c);

            
      
      
        return
      
      
        0
      
      
        ;

        }

        
      
      
        else
      
      
         {

            
      
      
        if
      
       (solve(s1, t, s2, r)) 
      
        return
      
      
        0
      
      
        ;

            
      
      
        if
      
       (solve(s2, t, s1, r)) 
      
        return
      
      
        0
      
      
        ;

        }

    }

    puts(
      
      
        "
      
      
        Death
      
      
        "
      
      
        );

    
      
      
        return
      
      
        0
      
      
        ;

}
      
    

顺便贴圆交模板,这回的应该没问题了。

      #include <cmath>
      
        

#include 
      
      <algorithm>


      
        using
      
      
        namespace
      
      
         std;




      
      
        const
      
      
        double
      
       PI = acos(-
      
        1.0
      
      
        );


      
      
        const
      
      
        double
      
       EPS = 1e-
      
        8
      
      
        ;




      
      
        int
      
       sgn(
      
        double
      
      
         d) {

    
      
      
        if
      
       (fabs(d)<EPS) 
      
        return
      
      
        0
      
      
        ;

    
      
      
        return
      
       d>
      
        0
      
      ?
      
        1
      
      :-
      
        1
      
      
        ;

}




      
      
        struct
      
      
         sp {

    
      
      
        double
      
      
         x, y;

    
      
      
        double
      
      
         pa;

    
      
      
        int
      
      
         cnt;

    sp() {}

    sp(
      
      
        double
      
       a, 
      
        double
      
      
         b): x(a), y(b) {}

    sp(
      
      
        double
      
       a, 
      
        double
      
       b, 
      
        double
      
       c, 
      
        int
      
      
         d): x(a), y(b), pa(c), cnt(d) {}

    
      
      
        bool
      
      
        operator
      
      <(
      
        const
      
       sp &rhs) 
      
        const
      
      
         {

        
      
      
        /*
      
      
         需要处理单点的情况时

        if (sgn(pa-rhs.pa)==0) return cnt>rhs.cnt;

        
      
      
        */
      
      
        return
      
       pa<
      
        rhs.pa;

    }

    
      
      
        void
      
       read() {scanf(
      
        "
      
      
        %lf%lf
      
      
        "
      
      , &x, &
      
        y);}

    
      
      
        void
      
       write() {printf(
      
        "
      
      
        %lf %lf\n
      
      
        "
      
      
        , x, y);}

};



sp 
      
      
        operator
      
      +(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       sp(u.x+v.x, u.y+
      
        v.y);

}



sp 
      
      
        operator
      
      -(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       sp(u.x-v.x, u.y-
      
        v.y);

}




      
      
        double
      
       det(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       u.x*v.y-v.x*
      
        u.y;

}




      
      
        double
      
       dir(
      
        const
      
       sp &p, 
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        return
      
       det(u-p, v-
      
        p);

}




      
      
        double
      
       dis(
      
        const
      
       sp &u, 
      
        const
      
       sp &
      
        v) {

    
      
      
        double
      
       dx = u.x-
      
        v.x;

    
      
      
        double
      
       dy = u.y-
      
        v.y;

    
      
      
        return
      
       sqrt(dx*dx+dy*
      
        dy);

}




      
      
        //
      
      
        计算两圆交点


      
      
        //
      
      
        输入圆心坐标和半径


      
      
        //
      
      
        返回两圆是否相交(相切不算)


      
      
        //
      
      
        如果相交,交点返回在a和b(从a到b为u的交弧)
      
      
        bool
      
       cirint(
      
        const
      
       sp &u, 
      
        double
      
       ru, 
      
        const
      
       sp &v, 
      
        double
      
       rv, sp &a, sp &
      
        b) {

    
      
      
        double
      
       d =
      
         dis(u, v);

    
      
      
        /*
      
      
         需要处理单点的情况时 覆盖的情况在这里不统计

    if (sgn(d-(ru+rv))>0 || sgn(d-fabs(ru-rv))<=0) return 0;

    
      
      
        */
      
      
        if
      
       (sgn(d-(ru+rv))>=
      
        0
      
       || sgn(d-fabs(ru-rv))<=
      
        0
      
      ) 
      
        return
      
      
        0
      
      
        ;

    sp c 
      
      = u-
      
        v;

    
      
      
        double
      
      
         ca, sa, cb, sb, csum, ssum;



    ca 
      
      = c.x/d, sa = c.y/
      
        d;

    cb 
      
      = (rv*rv+d*d-ru*ru)/(
      
        2
      
      *rv*d), sb = sqrt(
      
        1
      
      -cb*
      
        cb);

    csum 
      
      = ca*cb-sa*
      
        sb;

    ssum 
      
      = sa*cb+sb*
      
        ca;

    a 
      
      = sp(rv*csum, rv*
      
        ssum);

    a 
      
      = a+
      
        v;



    sb 
      
      = -
      
        sb;

    csum 
      
      = ca*cb-sa*
      
        sb;

    ssum 
      
      = sa*cb+sb*
      
        ca;

    b 
      
      = sp(rv*csum, rv*
      
        ssum);

    b 
      
      = b+
      
        v;



    
      
      
        return
      
      
        1
      
      
        ;

}



sp e[
      
      
        222
      
      
        ];


      
      
        int
      
       cover[
      
        111
      
      
        ];




      
      
        //
      
      
        求圆并


      
      
        //
      
      
        输入点数N,圆心数组p,半径数组r,答案数组s


      
      
        //
      
      
        s[i]表示被至少i个圆覆盖的面积(最普通的圆并就是s[1])
      
      
        void
      
       circle_union(
      
        int
      
       N, sp p[], 
      
        double
      
       r[], 
      
        double
      
      
         s[]) {

    
      
      
        int
      
      
         i, j, k;

    memset(cover, 
      
      
        0
      
      , 
      
        sizeof
      
      
         cover);

    
      
      
        for
      
       (i = 
      
        0
      
      ; i < N; ++
      
        i)

        
      
      
        for
      
       (j = 
      
        0
      
      ; j < N; ++
      
        j) {

            
      
      
        double
      
       rd = r[i]-
      
        r[j];

            
      
      
        //
      
      
        覆盖的情况在这里统计
      
      
        if
      
       (i!=j && sgn(rd)>
      
        0
      
       && sgn(dis(p[i], p[j])-rd)<=
      
        0
      
      
        )

                cover[j]
      
      ++
      
        ;

        }

    
      
      
        for
      
       (i = 
      
        0
      
      ; i < N; ++
      
        i) {

        
      
      
        int
      
       ecnt = 
      
        0
      
      
        ;

        e[ecnt
      
      ++] = sp(p[i].x-r[i], p[i].y, -PI, 
      
        1
      
      
        );

        e[ecnt
      
      ++] = sp(p[i].x-r[i], p[i].y, PI, -
      
        1
      
      
        );

        
      
      
        for
      
       (j = 
      
        0
      
      ; j < N; ++
      
        j) {

            
      
      
        if
      
       (j==i) 
      
        continue
      
      
        ;

            
      
      
        if
      
      
         (cirint(p[i], r[i], p[j], r[j], a, b)) {

                e[ecnt
      
      ++] = sp(a.x, a.y, atan2(a.y-p[i].y, a.x-p[i].x), 
      
        1
      
      
        );

                e[ecnt
      
      ++] = sp(b.x, b.y, atan2(b.y-p[i].y, b.x-p[i].x), -
      
        1
      
      
        );

                
      
      
        if
      
       (sgn(e[ecnt-
      
        2
      
      ].pa-e[ecnt-
      
        1
      
      ].pa)>
      
        0
      
      
        ) {

                    e[
      
      
        0
      
      ].cnt++
      
        ;

                    e[
      
      
        1
      
      ].cnt--
      
        ;

                }

            }

        }

        sort(e, e
      
      +
      
        ecnt);

        
      
      
        int
      
       cnt = e[
      
        0
      
      
        ].cnt;

        
      
      
        for
      
       (j = 
      
        1
      
      ; j < ecnt; ++
      
        j) {

            
      
      
        double
      
       pad = e[j].pa-e[j-
      
        1
      
      
        ].pa;

            s[cover[i]
      
      +cnt] += (det(e[j-
      
        1
      
      ], e[j])+r[i]*r[i]*(pad-sin(pad)))/
      
        2
      
      
        ;

            cnt 
      
      +=
      
         e[j].cnt;

        }

    }

}
      
    

[代码]ural 1913 Titan Ruins: Old Generators Are Fine Too


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论