zoukankan      html  css  js  c++  java
  • poj 1279 求半平面交的 面积(推荐)

    poj 1279    求半平面交的 面积

    题目来源:

    http://poj.org/problem?id=1279

    分析: 求半平面交的 面积

    代码如下:

    const double EPS = 1e-8 ;
    const int Max_N = 1505 ;
    double add(double a, double b){
        return (fabs(a + b) < EPS * (fabs(a) + fabs(b)) ) ?  0 : (a + b );
    }
    struct Point {
        double x, y;
        Point(){}
        Point(double x, double y):x(x) , y(y){}
        Point operator - (Point a){
            return Point(add(x , -a.x) , add(y , -a.y)) ;
        }
        Point operator + (Point a){
            return Point(add(x , a.x) , add(y , a.y)) ;
        }
        double operator ^(Point a){
            return add(x * a.y ,  - y * a.x) ;
        }
        Point operator * (double d){
            return Point(x * d , y * d) ;
        }
    };
    struct Line{  //有向直线
        Point st, ed;
        Line(){}
        Line(Point s, Point e){
            st = s ;
            ed = e ;
        }   
        bool onRight(Point a){ //点a在直线向量的右边
            return ((ed - st)^(a - st)) < 0 ;
        }
        bool parallel(Line l){
            return ((ed -st)^(l.ed - l.st)) == 0 ;
        }
        Point Crossnode(Line l){ //两直线的交点
            double t = (l.ed - l.st) ^(l.st - st) ;
            double t1 = (l.ed - l.st)^(ed - st) ;
            return st + (ed - st)*(t / t1) ;
        }
        double jijiao(){
            return atan2(ed.y - st.y , ed.x - st.x) ;
        }
        void write(){
            printf("%lf %lf %lf %lf
    " , st.x ,st.y ,ed.x ,ed.y) ;
        }
    };
    //排序函数 [优先顺序:1极角  2. 前面的直线在后面的左边 ]
    bool operator < (Line l, Line r){
        double lp = l.jijiao() ;
        double rp = r.jijiao() ;
        if( fabs(lp - rp) > EPS)
            return lp < rp ;
        return ((l.st - r.st)^(r.ed - r.st)) < -EPS ;
    }
    //用于计算的双端队列
    Line dequeue[Max_N] ;
    Point pt[Max_N] ;
    // 返回半平面交的 交点
    //获取 半平面交的 多边形(多边形的核) o(n log(2n))
    //参数: 向量集合line[l], 向量数量[ln] (半平面方向在向量的左边)
    //函数运行后 如果n[即返回多边形的点数量] 为 0 则不存在半平面交的多边形(不存在区域或区域面积无穷大)
    int halfPanelCross(Line line[] , int ln){
        int i, tn;
        sort(line, line  + ln ) ;
    // 平面在向量左边 的筛选
        for(i = tn = 1 ; i < ln ; i++){// 处理极角相同的,选择向量方向最左边的
            if(fabs(line[i].jijiao() - line[i -1].jijiao())  > EPS)
                line[tn++] = line[i] ;
        }
        ln = tn ;
        int bot = 0 , top = 1 ;
        dequeue[0] = line[0] ;
        dequeue[1] = line[1] ;
        for(i = 2 ; i < ln ; i++){
            if(dequeue[top].parallel(dequeue[top - 1])|| dequeue[bot].parallel(dequeue[bot + 1]))
                return 0 ;
            while(bot < top &&
                  line[i].onRight(dequeue[top].Crossnode(dequeue[top - 1])))
                top -- ;
            while(bot < top &&
                 line[i].onRight(dequeue[bot].Crossnode(dequeue[bot + 1])))
                bot ++ ;
            dequeue[++ top] = line[i] ;
        }
        while(bot < top &&
              dequeue[bot].onRight(dequeue[top].Crossnode(dequeue[top -1])))
            top -- ;
        while(bot < top &&
              dequeue[top].onRight(dequeue[bot].Crossnode(dequeue[bot + 1])))
            bot ++ ;
        if(top <= bot + 1) return 0 ;  // 若队列为空, 则空集
        int n = 0 ;
        //计算交点(注意不同直线形成的交点可能重合) 半平面交是凸多边形
        for(i = bot ; i < top ; i++)
            pt[n ++] = dequeue[i].Crossnode(dequeue[i + 1]) ;
        if(bot < top +1)
            pt[n ++] = dequeue[bot].Crossnode(dequeue[top]) ;
        return n ;
    }
    Line List[Max_N] ;
    Point p[Max_N] ;
    int main(){
        int t , i, j ;
        int m ;
        scanf("%d" , &t) ;
        while(t--){
            scanf("%d" , &m) ;
            for(i = 0 ; i < m ; i++)
                scanf("%lf%lf" , &p[i].x , &p[i].y) ;
            for(i = 0 ;  i < m ; i++){
                List[i] = Line(p[(i + 1) % m] , p[i]) ;
            }
            int n = halfPanelCross(List , m) ;
            double area = 0.0 ;
            if(n ==0)
                printf("0.00
    ") ;
            else{
                for(i = 0 ; i< n ; i++)
                    area += pt[i]^pt[(i + 1) %n] ;
                area = fabs(area) ;
                printf("%.2lf
    " , area * 0.5) ;
            }
        }
        return 0;
    }
  • 相关阅读:
    推荐谷歌浏览器12款常用的扩展
    推荐谷歌浏览器12款常用的扩展
    推荐VSCode12个比较实用的插件
    推荐VSCode12个比较实用的插件
    Linux中Shell循环结构for用法笔记
    django之上传图片
    django之中间件设置
    django之admin站点
    django之管理静态文件
    django之设置分页
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3699582.html
Copyright © 2011-2022 走看看