题解
- 首先要判断多边形使否是凸边形。对于连续的点a、b、c,就要判断ab×bc是否都是同号。
- 其次要判断圆心是否在多边形的内部,因为是凸边形,所以很好判断。对于连续的点a,b,c和圆心o,判断ba×bo和bc×bo的符号。如果存在同号,那么就是在外部。
- 最后就是判断圆心到边的距离和半径的关系了。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
int const N = 1000 + 10;
double eps = 1e-10;
double r,x,y;
int n;
typedef struct Point{ //点和向量
double x,y;
Point(){};
Point(double x,double y):x(x),y(y){};
Point operator - (const Point& e)const{ //减
return Point(x - e.x,y - e.y);
}
double operator ^ (const Point& e)const{ //叉乘
return x * e.y - y * e.x;
}
double operator * (const Point& e)const{ //点积
return x * e.x + y * e.y;
}
}Vector;
struct Line{ //直线的定义
Point a,b;
Line(){};
Line(Point a,Point b):a(a),b(b){}
};
Point p[N],o;
int dcmp(double x){ //判断符号
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
double length(Line line){ //线段的长度
return sqrt(pow(line.a.x - line.b.x,2) + pow(line.a.y - line.b.y,2));
}
double distance(Point p,Line line){ //点到直线距离
return fabs(((line.b - line.a) ^ (p - line.a)) / length(line));
}
bool formed(){ //判断是否是凸包
int flag;
for(int i=0;i<n;i++){
int j = (i + 1) % n, k = (i + 2) % n;
if(i == 0) flag = dcmp((p[j] - p[i]) ^ (p[k] - p[j]));
else if(flag * dcmp((p[j] - p[i]) ^ (p[k] - p[j])) < 0) return false;
}
return true;
}
bool fit(){
for(int i=0;i<n;i++){
int j = (i - 1 + n) % n, k = (i + 1) % n;
if(dcmp((p[j] - p[i]) ^ (o - p[i])) * dcmp((p[k] - p[i]) ^ (o - p[i])) >= 0) return false;
double dis = distance(o,Line(p[i],p[k]));
if(dcmp(r - dis) > 0) return false;
}
return true;
}
int main(){
while(~scanf("%d",&n) && n >= 3){
scanf("%lf%lf%lf",&r,&x,&y);
o = Point(x,y);
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
if(formed()){
if(fit()) printf("PEG WILL FIT\n");
else printf("PEG WILL NOT FIT\n");
}else printf("HOLE IS ILL-FORMED\n");
}
return 0;
}