题意:1.所有的点不能刚好能构成凸包输出:HOLE IS ILL-FORMED
2.否则如果圆不超出凸包输出:PEG WILL FIT,不然输出:PEG WILL NOT FIT
分析:先判断判断是不是凸包, 是凸包的情况下判断圆是否在凸包内(包括内切)。
判断凸包:获取凸包,如果最后顶点数和凸包顶点数不一样就不是。
判断圆是否在凸包内:判断圆心在凸包内,在则获取圆心到凸包边上的最小值。大于半径则不在。
判断圆心和凸包的关系:1.查看有向面积符号的一致性O(n)。2.二分极角判断O(log(n))。
2.否则如果圆不超出凸包输出:PEG WILL FIT,不然输出:PEG WILL NOT FIT
分析:先判断判断是不是凸包, 是凸包的情况下判断圆是否在凸包内(包括内切)。
判断凸包:获取凸包,如果最后顶点数和凸包顶点数不一样就不是。
判断圆是否在凸包内:判断圆心在凸包内,在则获取圆心到凸包边上的最小值。大于半径则不在。
判断圆心和凸包的关系:1.查看有向面积符号的一致性O(n)。2.二分极角判断O(log(n))。
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<string>
#include <map>
#include <vector>
#include<algorithm>
#include <complex>
#define eps 1e-8
#define INF 1e8
using namespace std;
typedef double TYPE;
inline int sgn(double x){return x < -eps ? -1 : ( x > eps? 1 : 0);}
struct Point
{
TYPE x, y;
Point(){}
Point(const TYPE &xx, const TYPE &yy):x(xx), y(yy){}
void input(){scanf("%lf %lf", &x, &y);}
void output(){ printf("%.2f %.2f\n", x, y);}
Point operator + (const Point &p)const{ return Point(x + p.x, y + p.y);}
Point operator - (const Point &p)const{return Point(x- p.x, y - p.y);}
Point operator / (const TYPE &w)const{return Point(x /w, y/w );}
Point operator * (const TYPE &w)const{ return Point(x * w, y * w);}
friend Point operator * (const TYPE &w, const Point &p){ return Point(w * p.x, w * p.y);}
bool operator < (const Point &p)const{ return x < p.x || ( x == p.x && y < p.y);}
friend double det(const Point &a, const Point &b){ return a.x* b.y - a.y * b.x;}
friend double dot(const Point &a, const Point &b){return a.x * b.x + a.y* b.y;}
double norm()const{ return sqrt(x * x + y * y);}
};
struct Line
{
Point s, t;
Line(){}
Line(Point ss, Point tt):s(ss), t(tt){}
double distPointToLine(const Point &p){
if(sgn(dot(t - s, p - s)) < 0)return (p - s).norm();
if(sgn(dot( s - t, p - t)) < 0)return (p - t).norm();
return (fabs(det(s - p, t - p))/ (s - t).norm());
}
};
struct Hull
{
int n;
vector<Point>v;
Hull( ){
v.resize(0);
}
void getHull(vector<Point> &ps){
int tSize = ps.size();
v.resize(0);
sort(ps.begin(), ps.end());
int m = 0;
for(int i = 0; i < tSize; i++){
while(m > 1 && sgn(det(v[m - 1] - v[m - 2], ps[i] - v[m - 2])) < 0)m--, v.pop_back();
v.push_back(ps[i]);
m++;
}
int k = m;
for(int i = tSize - 2; i >= 0; i--){
while(m > k && sgn(det(v[m - 1] - v[m - 2], ps[i] - v[m - 2])) < 0 )m--, v.pop_back();
v.push_back(ps[i]);
m++;
}
v.resize(m);
if(m > 0)v.resize(m - 1);
// for(int i = 0;i < v.size();i ++){
// v[i].output();
// }
}
bool isContain(const Point &t){ // 16MS过~
int sign = 0;
int tSize = v.size();
for(int i = 0; i < tSize; i++){
if(sgn(det(t - v[i], t - v[(i + 1)%tSize])) == 0){ return true;}//边界上
}
for(int i = 0; i < tSize; i++){
int tSign = sgn(det(v[(i + 1)%tSize] - t, v[i] - t));
if(tSign){
if(sign){
if(sign != tSign)return false;//外面
}else {
sign = tSign;
}
}
}
return true;//内部
}
//二分极角,Olog(n)版本判断点和凸包的位置关系, 0MS过,神奇!
bool isContainOlogn(Point &t){
int n = v.size(), l = 0, r = n;
Point g = (v[0] + v[n / 3] + v[n * 2/ 3])/3.0;//凸包内部一个点(其中一个三角形的重心);
while(l + 1< r){
int mid = (r + l)>> 1;
int k = sgn(det(v[l] - g, v[mid] - g));
int res1 = sgn(det(v[l] - g, t - g));
int res2 = sgn(det(v[mid] - g, t - g));
if(k > 0){
if(res1>= 0 && res2< 0){
r = mid;
}else {
l = mid;
}
}else {
if(res1 < 0 &&res2 >=0 ){
l = mid;
}else {
r = mid;
}
}
}
r %= n;
int res = sgn(det(v[r] - t, v[l] - t));
if(res == -1 || res == 0)return true;
return false;
}
}hull;
vector<Point>ps;
Point co;
double r;
int n;
void init(){
scanf("%lf", &r);
co.input();
ps.resize(n);
for(int i = 0; i < n; i++){
ps[i].input();
}
}
void solve(){
hull.getHull(ps);
if(ps.size() != hull.v.size()){
puts("HOLE IS ILL-FORMED");
}else {
if(hull.isContainOlogn(co)){
int tSize = hull.v.size();
double min_d = INF;
for(int i = 0;i < tSize; i++){
Line line(hull.v[i], hull.v[(i+1)%tSize]);
min_d = min(line.distPointToLine(co), min_d);
}
if(sgn(min_d - r) >= 0){
puts("PEG WILL FIT");
}else {
puts("PEG WILL NOT FIT");
}
}else {
puts("PEG WILL NOT FIT");
}
}
}
int main()
{
while(scanf("%d", &n), n > 2){
init();
solve();
}
return 0 ;
}