zoukankan      html  css  js  c++  java
  • POJ

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

    题意

    按照顺时针或逆时针方向输入一个n边形的顶点坐标集,先判断这个n边形是否为凸包。

    再给定一个圆形(圆心坐标和半径),判断这个圆是否完全在n边形内部。

    分析

    1.判断给出了多边形是不是凸多边形。

    2.判断圆包含在凸多边形中:一定要保证圆心在凸多边形里面。然后判断圆心到每条线段的距离要大于等于半径。。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.h>
    
    using namespace std;
    
    const double eps = 1e-8;
    const double PI = acos(-1.0);
    int sgn(double x)
    {
        if(fabs(x) < eps)return 0;
        if(x < 0)return -1;
        else return 1;
    }
    struct Point
    {
        double x,y;
        Point(){}
        Point(double _x,double _y)
        {
            x = _x;y = _y;
        }
        Point operator -(const Point &b)const
        {
            return Point(x - b.x,y - b.y);
        }
        //叉积
        double operator ^(const Point &b)const
        {
            return x*b.y - y*b.x;
        }
        //点积
        double operator *(const Point &b)const
        {
            return x*b.x + y*b.y;
        }
        void input()
        {
            scanf("%lf%lf",&x,&y);
        }
    };
    struct Line
    {
        Point s,e;
        Line(){}
        Line(Point _s,Point _e)
        {
            s = _s;e = _e;
        }
    };
    //*两点间距离
    double dist(Point a,Point b)
    {
        return sqrt((a-b)*(a-b));
    }
    //判断凸多边形
    //允许共线边
    //点可以是顺时针给出也可以是逆时针给出
    //点的编号1~n-1
    bool isconvex(Point poly[],int n)
    {
        bool s[3];
        memset(s,false,sizeof(s));
        for(int i = 0;i < n;i++)
        {
            s[sgn( (poly[(i+1)%n]-poly[i])^(poly[(i+2)%n]-poly[i]) )+1] = true;
            if(s[0] && s[2])return false;
        }
        return true;
    }
    //点到线段的距离
    //返回点到线段最近的点
    Point NearestPointToLineSeg(Point P,Line L)
    {
        Point result;
        double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));
        if(t >= 0 && t <= 1)
        {
            result.x = L.s.x + (L.e.x - L.s.x)*t;
            result.y = L.s.y + (L.e.y - L.s.y)*t;
        }
        else
        {
            if(dist(P,L.s) < dist(P,L.e))
                result = L.s;
            else result = L.e;
        }
        return result;
    }
    //*判断点在线段上
    bool OnSeg(Point P,Line L)
    {
        return
        sgn((L.s-P)^(L.e-P)) == 0 &&
        sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
        sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
    }
    //*判断点在凸多边形内
    //点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
    //点的编号:0~n-1
    //返回值:
    //-1:点在凸多边形外
    //0:点在凸多边形边界上
    //1:点在凸多边形内
    int inConvexPoly(Point a,Point p[],int n)
    {
        for(int i = 0;i < n;i++)
        {
            if(sgn((p[i]-a)^(p[(i+1)%n]-a)) < 0)return -1;
            else if(OnSeg(a,Line(p[i],p[(i+1)%n])))return 0;
        }
        return 1;
    }
    //*判断线段相交
    bool inter(Line l1,Line l2)
    {
        return
        max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
        sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 &&
        sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0;
    }
    //*判断点在任意多边形内
    //射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
    //返回值
    //-1:点在凸多边形外
    //0:点在凸多边形边界上
    //1:点在凸多边形内
    int inPoly(Point p,Point poly[],int n)
    {
        int cnt;
        Line ray,side;
        cnt = 0;
        ray.s = p;
        ray.e.y = p.y;
        ray.e.x = -100000000000.0;//-INF,注意取值防止越界
    
        for(int i = 0;i < n;i++)
        {
            side.s = poly[i];
            side.e = poly[(i+1)%n];
    
            if(OnSeg(p,side))return 0;
    
            //如果平行轴则不考虑
            if(sgn(side.s.y - side.e.y) == 0)
                continue;
    
            if(OnSeg(side.s,ray))
            {
                if(sgn(side.s.y - side.e.y) > 0)cnt++;
            }
            else if(OnSeg(side.e,ray))
            {
                if(sgn(side.e.y - side.s.y) > 0)cnt++;
            }
            else if(inter(ray,side))
                cnt++;
        }
        if(cnt % 2 == 1)return 1;
        else return -1;
    }
    Point p[110];
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int n;
        double R,x,y;
        while(scanf("%d",&n) == 1)
        {
            if(n < 3)break;
            scanf("%lf%lf%lf",&R,&x,&y);
            for(int i = 0 ;i < n;i++)
                p[i].input();
            if(!isconvex(p,n))
            {
                printf("HOLE IS ILL-FORMED
    ");
                continue;
            }
            Point P = Point(x,y);
            if(inPoly(P,p,n) < 0)
            {
                printf("PEG WILL NOT FIT
    ");
                continue;
            }
            bool flag = true;
            for(int i = 0;i < n;i++)
            {
                if(sgn(dist(P,NearestPointToLineSeg(P,Line(p[i],p[(i+1)%n]))) - R) < 0 )
                {
                    flag = false;
                    break;
                }
            }
            if(flag)printf("PEG WILL FIT
    ");
            else printf("PEG WILL NOT FIT
    ");
        }
        return 0;
    }
  • 相关阅读:
    “automation服务器不能创建对象”的问题的解决方案大全
    转载区分C#中的Abstract函数和Virtual函数
    DOS批处理
    数据库设计范式
    java 内存查看工具
    Java内存溢出详解
    Struts2 循环编辑指定次数
    Selenium 使用
    spring security 获取当前用户信息
    由MyEclipse内存不足谈谈JVM内存
  • 原文地址:https://www.cnblogs.com/fht-litost/p/9350179.html
Copyright © 2011-2022 走看看