题目描述
传送门
题意:
给出一个半径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;
}