大致思路:首先对于所给的洞的点,判断是否是凸多边形,图形的输入和输出可以是顺时针或者逆时针,而且允许多点共线
Debug 了好几个小时,发现如下问题
判断三点是否共线,可用斜率公式判断
POINT point_A, point_B, point_C; if(point_A.x == point_B.x || point_B.x == point_C.x){ if(point_A.x == point_B.x && point_B.x == point_C.x) continue; }else{ if((point_B.y - point_A.y) / (point_B.x - point_A.x) \ == (point_C.y - point_B.y) / (point_C.x - point_B.x)) continue; }
其次,判断圆是否和多边形相切的时候,应用:
if(Ptol(point, line2) - rr >= 0){
而不是:
if(Ptol(point, line2) - rr >= eps){//eps = 1e-9
否则会出错。
贴代码了QAQ
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring> #include <cmath> #include <stack> #include <queue> #include <vector> #include <algorithm> #define ll long long #define Max(a,b) (((a) > (b)) ? (a) : (b)) #define Min(a,b) (((a) < (b)) ? (a) : (b)) #define Abs(x) (((x) > 0) ? (x) : (-(x))) using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 220; const double eps = 1e-9; int gcd(int a,int b){ return b == 0 ? a : gcd(b, a % b); } struct POINT{ double x; double y; POINT() : x(0), y(0) {}; POINT(double _x_, double _y_) : x(_x_), y(_y_) {}; }; struct SEG{ POINT a; POINT b; SEG() {}; SEG(POINT _a_, POINT _b_) : a(_a_), b(_b_) {}; }; struct LINE{ POINT a; POINT b; LINE() {}; LINE(POINT _a_, POINT _b_) : a(_a_), b(_b_) {}; }; struct LINE2{ double A, B, C; LINE2 () {}; LINE2(double _A_, double _B_, double _C_): A(_A_), B(_B_), C(_C_) {}; }; LINE2 Line2line(const LINE & L){ LINE2 L2; L2.A = L.b.y - L.a.y; L2.B = L.a.x - L.b.x; L2.C = L.b.x * L.a.y - L.a.x * L.b.y; return L2; } struct POLY{ int n; double * x; double * y; POLY() : n(0), x(NULL), y(NULL) {}; POLY(int _n_, const double * _x_, const double * _y_){ n = _n_; x = new double[n + 1]; memcpy(x, _x_, n * sizeof(double)); x[n] = _x_[0]; y = new double[n + 1]; memcpy(y, _y_, n * sizeof(double)); y[n] = _y_[0]; } }; POINT vertex(const POLY & poly, int idx){ idx %= poly.n; return POINT(poly.x[idx], poly.y[idx]); } SEG Edge(const POLY & poly, int idx){ idx %= poly.n; return SEG(POINT(poly.x[idx], poly.y[idx]), POINT(poly.x[idx + 1], poly.y[idx + 1])); } void Coefficient(const LINE & L, double & A, double & B, double & C){ A = L.b.y - L.a.y; B = L.a.x - L.b.x; C = L.b.x * L.a.y - L.a.x * L.b.y; } double Ptol(const POINT p, const LINE2 L){ return Abs(L.A * p.x + L.B * p.y + L.C) / sqrt(L.A * L.A + L.B * L.B); } bool IsEqual(double a, double b){ return (Abs(a - b) < eps); } bool IsEqual(const POINT & a, const POINT & b){ return (IsEqual(a.x, b.x) && IsEqual(a.y, b.y)); } bool IsEqual(const LINE & A, const LINE & B){ double A1, B1, C1; double A2, B2, C2; Coefficient(A, A1, B1, C1); Coefficient(B, A2, B2, C2); return IsEqual(A1 * B2, A2 * B1) && IsEqual(A1 * C2, A2 * C1) && IsEqual(B1 * C2, B2 * C1); } double Cross(const POINT & a, const POINT & b, const POINT &o){ return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y); } bool IsParallel(const LINE & A, const LINE & B){ double A1, B1, C1; double A2, B2, C2; Coefficient(A, A1, B1, C1); Coefficient(B, A2, B2, C2); /* return (A1 * B2 == A2 * B1) && ((A1 * C2 != A2 * C1) || (B1 * C2 != B2 * C1)); */ return (A1 * B2 == A2 * B1); } bool IsIntersect(const LINE & A, const LINE & B){ return !IsParallel(A, B); } bool IsIntersect(const SEG & u, const SEG & v){ return (Cross(v.a, u.b, u.a) * Cross(u.b, v.b, u.a) >= 0) && (Cross(u.a, v.b, v.a) * Cross(v.b, u.b, v.a) >= 0) && (Max(u.a.x, u.b.x) >= Min(v.a.x, v.b.x)) && (Max(v.a.x, v.b.x) >= Min(u.a.x, u.b.x)) && (Max(u.a.y, u.b.y) >= Min(v.a.y, v.b.y)) && (Max(v.a.y, v.b.y) >= Min(u.a.y, u.b.y)); } bool IsOnSeg(const SEG & seg, const POINT & p){ return (IsEqual(p, seg.a) || IsEqual(p, seg.b)) || (((p.x - seg.a.x) * (p.x - seg.b.x) < 0 || (p.y - seg.a.y) * (p.y - seg.b.y) < 0) && (IsEqual(Cross(seg.b, p, seg.a), 0))); } bool IsOnPoly(const POLY & poly, const POINT & p){ for(int i = 0; i < poly.n; ++i){ if(IsOnSeg(Edge(poly, i), p)){ return true; } } return false; } bool IsInPoly(const POLY & poly, const POINT & p){ SEG L(p, POINT(INF, p.y)); int count = 0; for(int i = 0; i < poly.n; ++i){ SEG S = Edge(poly, i); if(IsOnSeg(S, p)){ return true; } if(!IsEqual(S.a.y, S.b.y)){ POINT & q = (S.a.y > S.b.y) ? (S.a) : (S.b); if(IsOnSeg(L, q)){ ++count; } else if(!IsOnSeg(L, S.a) && !IsOnSeg(L, S.b) && IsIntersect(S, L)){ ++count; } } } return (count % 2 != 0); } POINT InCenter(const POLY & poly){ double S, Si, Ax, Ay; POINT p; Si = (poly.x[poly.n - 1] * poly.y[0] - poly.x[0] * poly.y[poly.n - 1]); S = Si; Ax = Si * (poly.x[0] + poly.x[poly.n - 1]); Ay = Si * (poly.y[0] + poly.y[poly.n - 1]); for(int i = 1; i < poly.n; ++i){ Si = (poly.x[i - 1] * poly.y[i] - poly.x[i] * poly.y[i - 1]); Ax += Si * (poly.x[i - 1] + poly.x[i]); Ay += Si * (poly.y[i - 1] + poly.y[i]); S += Si; } S = S * 3; return POINT(Ax/S, Ay/S); } double Area(const POLY & poly){ if(poly.n < 3) return double(0); double s = poly.y[0] * (poly.x[poly.n - 1] - poly.x[1]); for(int i = 1; i < poly.n; ++i){ s += poly.y[i] * (poly.x[i - 1] - poly.x[(i + 1) % poly.n]); } return s / 2; } int PointInedge(const POLY & poly){ int ans = 0; for(int i = 0; i < poly.n; ++i){ double xx = Abs(poly.x[i] - poly.x[i + 1]); double yy = Abs(poly.y[i] - poly.y[i + 1]); if(xx == 0 && yy == 0) ans += 0; else if(xx == 0) ans += yy - 1; else if(yy == 0) ans += xx- 1 ; else ans += gcd(xx, yy) - 1; } return ans + poly.n; } bool IsConvexPolygon(const POLY & poly){ double ans ,cnt = 1.0; bool flag ,real = false; for(int i = 0; i < poly.n; ++i){ ans = (poly.x[i] - poly.x[(i + 2) % poly.n])\ * (poly.y[(i + 1) % poly.n] - poly.y[(i + 2) % poly.n])\ - (poly.x[(i + 1) % poly.n] - poly.x[(i + 2) % poly.n])\ * (poly.y[i] - poly.y[(i + 2) % poly.n]); POINT point_A, point_B, point_C; if(point_A.x == point_B.x || point_B.x == point_C.x){ if(point_A.x == point_B.x && point_B.x == point_C.x) continue; }else{ if((point_B.y - point_A.y) / (point_B.x - point_A.x) \ == (point_C.y - point_B.y) / (point_C.x - point_B.x)) continue; } if(real && cnt * ans < eps) return false; cnt = ans; real = true; } return true; } double x[20011], y[20011]; int main(){ int i, j, k; int t, n, m; double rr, xx, yy; while(EOF != scanf("%d",&n)){ if(n < 3) break; POINT point; scanf("%lf%lf%lf",&rr,&point.x,&point.y); for(i = 0; i < n; ++i) scanf("%lf%lf",&x[i],&y[i]); POLY poly(n, x, y); if(!IsConvexPolygon(poly)) printf("HOLE IS ILL-FORMED\n"); else{ if(!IsInPoly(poly, point)){ printf("PEG WILL NOT FIT\n"); } else{ for(i = 0; i < n; ++i){ SEG seg = Edge(poly, i); LINE line; LINE2 line2; line.a = seg.a; line.b = seg.b; line2 = Line2line(line); if(Ptol(point, line2) - rr >= 0){ continue; } else{ printf("PEG WILL NOT FIT\n"); break; } } if(i == n){ printf("PEG WILL FIT\n"); } } } } return 0; }