zoukankan      html  css  js  c++  java
  • POJ 3449 Geometric Shapes (多边形)

    • 题意: 给出一个多边形和一个圆,先判断多边形是否为凸多边形,在判断圆是否在多边形内
    • 思路: 整理一下板子。
    
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N = 1e3+10;
    const double eps = 1e-8;
    inline int sgn(double x){
        if(fabs(x)<eps) return 0;
        return x<0? -1:1;
    }
    
    struct point{
        double x,y;
        point(double a=0,double b=0){
            x = a, y = b;
        }
        point operator -(const point &b)const{
            return point(x-b.x,y-b.y);
        }
        bool operator <(const point &b)const{
            return x<b.x-eps;
        }
        bool operator == (const point &b)const{
            return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
        }
        void transxy(double b){
            double tx = x,  ty = y;
            x = tx*cos(b) - ty*sin(b);
            y = tx*sin(b) + ty*cos(b);
        }
        double norm(){
            return sqrt(x*x+y*y);
        }
    };
    inline double det(const point &a,const point &b){
        return a.x*b.y - a.y*b.x;
    }
    inline double dot(const point &a,const point &b){
        return a.x*b.x+ a.y*b.y;
    }
    inline double dist(const point &a,const point &b){
        return (a-b).norm();
    }
    double area(point a,point b,point c){
        return det(b-a,c-b);
    }
    struct line{
        point s,e;
        line(){}
        line(point s,point e):s(s),e(e){}
    };
    inline bool parallel(line &l1,line &l2){
        return !sgn(det(l1.e - l1.s,l2.e-l2.s));
    }
    inline bool point_on_seg(point &p,line &a){
        return sgn(det(p-a.s,p-a.e))==0 && sgn(dot(p-a.s,p-a.e))<=0;
    }
    // 线段与线段相交
    inline bool cross(line l1,line l2){
        line vec = line(l1.s,l1.e-l1.s);    // l1 的向量9
        if(parallel(l1,l2))     // 平行(重合),则点在线上才相交
            return point_on_seg(l1.s,l2) || point_on_seg(l1.e,l2)
                || point_on_seg(l2.s,l1) || point_on_seg(l2.e,l1);
        if(sgn(det(l2.s-vec.s,vec.e)*det(vec.e,l2.e-vec.s))==-1)
            return false; 
        if(sgn(det(l2.s-l1.s,l2.e-l1.s)*det(l2.s-l1.e,l2.e-l1.e))==1)
            return false;
        return true;
    }
    // 线段与直线相交
    // 手写 uncheck
    bool segcorseg(line l1,line l2){
        // 两端叉积符号不同,则在不同侧,说明相交   
        // = 0 表示端点在线上
        return sgn(det(l1.a - l2.a, l1.b - l2.a)) * sgn(det(l1.a - l2.b , l1.b - l2.b)) <= 0
        || sgn(det(l2.a - l1.a,l2.b - l1.a)) * sgn(det(l2.a - l1.b, l2.b - l1.b)) <= 0;
    }
    
    // 极角排序
    point start;
    bool cmp(const point &a,const point &b){
        double x = det(a-start,b-start);
        if(sgn(x)==0)   return dist(start,a) < dist(start,b);
        else return x>0;
    }
    struct polygon{
        int n;
        point a[N];
        polygon(){}
        bool isTu(){
            // 凸多边形判断
            // 相邻三点构成三角形 叉积符号相同
            bool s[3];  // -1 0 1 是否存在, 
            s[0] = s[1] = s[2] = 0;
            for(int i=0;i<n;++i){
                s[sgn(area(a[i],a[(i+1)%n],a[(i+2)%n]))+1] = 1;
                if(s[0] && s[2])    return false;   // 有正又有负不行
            }
            return true;
        }
        bool inPoly(point p){
            // 点在多边形内
            // 先以a[0]为源点 进行极角排序
            start = a[0];
            sort(a,a+n,cmp);
            int cnt = 0 ;
            line ray,side;  // 点所在平行y轴射线,当前多边形的边
            ray.s = p;  ray.e.y = p.y;  ray.e.x = -1e9;
            for(int i=0;i<n;++i){
                side.s = a[i];
                side.e = a[(i+1)%n];
                if(point_on_seg(p,side))   return 1; // 如果点在边界上,也算在多边形内
                if(sgn(side.s.y-side.e.y)==0)   continue; // 平行 不计算
                if(point_on_seg(side.s,ray)){     // 起点在射线上
                    if(sgn(side.s.y - side.e.y) > 0) cnt++; // 小于等于0 则不会在多边形内
                } 
                else if(point_on_seg(side.e,ray)){
                    if(sgn(side.e.y - side.s.y) > 0) cnt++;
                }
                else if(cross(ray,side))   // 线段相交
                    cnt++;          
            }
            return cnt%2; // 相交点数为奇数,在多边形内
        }
    }poly;
    
    int main(){
        // freopen("2.out","w",stdout);
        int n,pos;  point center; double r;
        while(~scanf("%d",&n) && n>2){
            scanf("%lf%lf%lf",&r,&center.x,&center.y);
            poly.n = n; pos = 0;
            for(int i=0;i<n;++i){
                scanf("%lf%lf",&poly.a[i].x,&poly.a[i].y);
                if(poly.a[i].y < poly.a[pos].y || (sgn(poly.a[i].y-poly.a[pos].y)==0 && poly.a[i].x < poly.a[pos].x))
                    pos = i;
            }
    
            if(poly.isTu()){
                // 及左下角点为源点
                swap(poly.a[0],poly.a[pos]);
                if(!poly.inPoly(center)){
                    puts("PEG WILL NOT FIT");
                    continue;
                }
                double d;
                int no = 0;
                for(int i=0;i<n;++i){
                    // 源点到这条线的距离
                    d = fabs(det(center-poly.a[i],poly.a[(i+1)%n]-poly.a[i]))/dist(poly.a[i],poly.a[(i+1)%n]);
                    // r > d 包不住
                    if(sgn(d-r)==-1){
                        no = 1;
                        break;
                    }
                }
                if(no)  puts("PEG WILL NOT FIT");
                else puts("PEG WILL FIT");
            }else{
                puts("HOLE IS ILL-FORMED");
            }
        }
        
    
        return 0;
    }
    
  • 相关阅读:
    Django框架---- 信号
    算法----迷宫问题
    算法----数据结构
    算法----其他排序
    Twisted简介
    爬虫----selenium模块
    爬虫----Scrapy框架
    爬虫----requests模块
    关于电脑运行ubunut出现严重发热的问题
    基本操作命令详解
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11647329.html
Copyright © 2011-2022 走看看