zoukankan      html  css  js  c++  java
  • poj 3525 Most Distant Point from the Sea 半平面交 + 二分

    题目来源:

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

    分析:
    题意:给定一个凸多边形,求多边形中距离边界最远的点到边界的距离。
    思路 : 每次将凸多边形每条边往里平移d,判断是否存在核;二分d即可。

    多边形边上的点(x , y)往里平移d 后的 坐标: s , e  为向量的 起点和终点, len 为起点和终点的距离, h 为平移的距离

    x' = x + dx 

    y' = y + dy

    dx = ( s.y - e.y ) / len * h ,( 原理 是 利用 三角形的相似比 )

    dy = ( e.x - s.x  ) / len * h ;

    代码如下:

    using namespace std ;
    const double EPS = 1e-10 ;
    const int Max_N = 105 ;
    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) ;
        }
        double dist(Point a){
            return sqrt( add((x - a.x) * (x - a.x) , (y - a.y)*(y - a.y) ) ) ;
        }
    };
    struct Line{
        Point st, ed;
        Line(){}
        Line(Point st, Point ed):st(st),ed(ed){}
        bool onRight(Point a){ // 点在线右边
            return ((ed - st)^(a - st)) < 0 ;
        }
        bool parallel(Line l){
            return ((ed - st)^(l.ed - l.st)) == 0 ;
        }
        Point CrossNode(Line l){
            double d1 = (l.ed - l.st)^(l.st - st) ;
            double d2 = (l.ed - l.st)^(ed - st) ;
            return st + (ed - st)*(d1 / d2) ;
        }
        double jijiao(){
            return atan2(ed.y - st.y , ed.x - st.x) ;
        }
    };
    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)) < 0 ;
    }
    Line dequeue[Max_N] ;
    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] ;
        Point topcross ,botcross ;
        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(topcross = dequeue[top].CrossNode(dequeue[top - 1])))
                  top -- ;
            while(bot < top &&
                  line[i].onRight( botcross = dequeue[bot].CrossNode(dequeue[bot + 1])))
                  bot ++ ;
            dequeue[++ top] = line[i] ;
        }
        while(bot < top &&
              dequeue[bot].onRight(topcross = dequeue[top].CrossNode(dequeue[top - 1])))
              top -- ;
        while(bot < top &&
              dequeue[top].onRight(botcross = dequeue[bot].CrossNode(dequeue[bot + 1])))
              bot ++ ;
        if(top <= bot + 1) return 0 ;
        return 1;
    }
    Line tmp[Max_N] ;
    Line List[Max_N] ;
    void ploygonChange(double h, int ln){
        double len , dx ,dy ;
        for(int i= 0 ; i < ln ; i++){
            len = List[i].ed.dist(List[i].st) ;
            dx = (List[i].st.y - List[i].ed.y) / len * h ;
            dy = (List[i].ed.x - List[i].st.x) / len * h ;
            tmp[i].st.x = List[i].st.x + dx ;
            tmp[i].st.y = List[i].st.y + dy ;
            tmp[i].ed.x = List[i].ed.x + dx;
            tmp[i].ed.y = List[i].ed.y + dy ;
        }
    }
    double  BinSearch(int ln){
        double l , r, mid ;
        l = 0.0 , r = 20000.0 ;
        while(l + EPS < r){
            mid = (l + r) * 0.5 ;
            ploygonChange(mid , ln ) ;
            if(halfPanelCross(tmp , ln))
                l = mid ;
            else r = mid ;
        }
        return l;
    }
    int main(){
        int n;
        Point p[Max_N] ;
        while(scanf("%d" , &n) && n){
            for(int i = 0 ; i < n ; i++)
                scanf("%lf%lf" , &p[i].x , &p[i].y) ;
            for(int i = 0 ; i < n ; i++)
                List[i] = Line(p[i] , p[(i+1) % n]) ;
            double tt = BinSearch(n) ;
            printf("%.6lf
    " ,tt) ;
        }
        return 0;
    }
  • 相关阅读:
    九月学习计划与自我成长
    sqlyog无法连接mysql8.0的处理办法
    MySQL详细的攻略和玩法
    输入net start mysql显示MySQL 服务正在启动 . MySQL 服务无法启动。 服务没有报告任何错误。 请键入 NET HELPMSG 3534 以获得更多的帮助。
    MySQL详细安装教程
    2019上半年程序设计年度总结
    PTA12
    C#实现文本文件字符过滤
    C#字符串string和内存流MemoryStream及比特数组byte[]
    C# 流总结
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3700587.html
Copyright © 2011-2022 走看看