[POJ1584]A Round Peg in a Ground Hole(计算几何)

题目描述

传送门
题意:
给出一个半径R、一个点O、顺时针或者逆时针给出一个多边形
首先判断多边形是否为凸多边形,如果不是输出HOLE IS ILL-FORMED
然后再判断以O为圆心以R为半径的圆是否完全在多边形里,是则输出PEG WILL FIT,否则输出PEG WILL NOT FIT

题解

判断凸多边形用叉积判断即可
然后可以利用判断点是否在多边形内的方法(射线法)来做第二问
由于是凸多边形直接用DisTL就可以了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 100005

const double eps=1e-9;
int dcmp(double x)
{
    if (x<=eps&&x>=-eps) return 0;
    return (x>0)?1:-1;
}
struct Vector
{
    double x,y;
    Vector(double X=0,double Y=0)
    {
        x=X,y=Y;
    }
};
typedef Vector Point;
Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A,double a) {return Vector(A.x*a,A.y*a);}

int n,ty;
double R,x,y;
Point o,poly[N];
bool flag;

double Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}
double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}
double Len(Vector A)
{
    return sqrt(Dot(A,A));
}
double DisTL(Point P,Point A,Point B)
{
    Vector v=B-A,w=P-A;
    return fabs(Cross(v,w)/Len(v));
}
bool PInP(Point P)
{
    int cnt=0,a,b,c;
    for (int i=1;i<=n;++i)
    {
        if (dcmp(DisTL(P,poly[i],poly[i%n+1])-R)<0) return false;
        a=dcmp(Cross(poly[i%n+1]-poly[i],P-poly[i]));
        b=dcmp(poly[i].y-P.y);
        c=dcmp(poly[i%n+1].y-P.y);
        if (a<0&&b>=0&&c<0) ++cnt;
        if (a>0&&b<=0&&c>0) --cnt;
    }
    if (cnt) return true;
    else return false;
}
int main()
{
    while (~scanf("%d",&n))
    {
        if (n<3) break;
        scanf("%lf%lf%lf",&R,&x,&y);
        o=Point(x,y);
        for (int i=1;i<=n;++i)
        {
            scanf("%lf%lf",&x,&y);
            poly[i]=Point(x,y);
        }
        flag=true;ty=0;
        for (int i=1;i<=n;++i)
        {
            int c=dcmp(Cross(poly[i%n+1]-poly[i],poly[(i+1)%n+1]-poly[i%n+1]));
            if (!c) continue;
            if (!ty) ty=c;
            else
            {
                if (ty!=c)
                {
                    flag=false;
                    break;
                }
            }
        }
        if (!flag)
        {
            puts("HOLE IS ILL-FORMED");
            continue;
        }
        flag=PInP(o);
        if (!flag) puts("PEG WILL NOT FIT");
        else puts("PEG WILL FIT");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值