POJ 1584 A Round Peg in a Ground Hole
先判断是不是N多边形,求一下凸包,如果所有点都用上了,那么就是凸多边形
判断圆是否在多边形内,
先排除圆心在多边形外的情况
剩下的情况可以利用圆心到每条边的最短距离与半径的大小来判断
#include<cstdio> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<list> #include<algorithm> using namespace std; const double eps=1e-8; const double pi=2*asin(1.0); struct point { double x,y; double alpha; double len2; int id; } p[200]; int T,n; vector<point>v; vector<int>ans; double MinY; int MinId; bool cmp(const point &a, const point &b) { if(fabs(a.alpha-b.alpha)<eps) return a.len2<b.len2; return a.alpha<b.alpha; } double len2(point a,point b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } double f(point a,point b,point c) //返回点a所对应的角的弧度 { double B2=(double)len2(a,c); double C2=(double)len2(a,b); double A2=(double)len2(b,c); double COSA=(B2+C2-A2)/(2*sqrt(B2)*sqrt(C2)); return pi-acos(COSA); } double GetPointDistance(point p1, point p2) { return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); } double GetNearestDistance(point PA, point PB, point P3) { double a,b,c; a=GetPointDistance(PB,P3); if(a<=0.00001) return 0.0f; b=GetPointDistance(PA,P3); if(b<=0.00001) return 0.0f; c=GetPointDistance(PA,PB); if(c<=0.00001) return a; if(a*a>=b*b+c*c) return b; if(b*b>=a*a+c*c) return a; double l=(a+b+c)/2; double s=sqrt(l*(l-a)*(l-b)*(l-c)); return 2*s/c; } bool check(point T) { double sum=0; for(int i=0;i<ans.size();i++) sum=sum+pi-(f(T,p[ans[i]],p[ans[(i+1)%ans.size()]])); if(fabs(sum-2*pi)<eps) return 0; return 1; } int main() { double pegRadius ,pegX ,pegY ; while(~scanf("%d", &n)) { if(n<3) break; scanf("%lf%lf%lf",&pegRadius,&pegX,&pegY); MinY=9999999999999; for(int i=1; i<=n; i++) { scanf("%lf%lf", &p[i].x, &p[i].y); p[i].id=i; if(p[i].y<MinY) { MinY=p[i].y; MinId=i; } } ans.clear(); point pre; pre.x=-9999999999999; pre.y=p[MinId].y; point now; now.x=p[MinId].x; now.y=p[MinId].y; now.id=MinId; for(int i=1; i<=n; i++) { v.clear(); for(int k=1; k<=n; k++) { if(p[k].id!=now.id) { p[k].alpha=f(now,p[k],pre); p[k].len2=len2(p[k],now); v.push_back(p[k]); } } sort(v.begin(),v.end(),cmp); ans.push_back(v[0].id); if(v[0].id==MinId) break; pre.x=now.x; pre.y=now.y; pre.id=now.id; now.x=v[0].x; now.y=v[0].y; now.id=v[0].id; } if(ans.size()<n) printf("HOLE IS ILL-FORMED\n"); else { bool fail=0; point T; T.x=pegX; T.y=pegY; if(check(T)) {fail=1;} else { for(int i=0; i<ans.size(); i++) { double len=GetNearestDistance(p[ans[i]],p[ans[(i+1)%ans.size()]],T); if(len+eps<=pegRadius) fail=1; } } if(fail==0) printf("PEG WILL FIT\n"); else printf("PEG WILL NOT FIT\n"); } } return 0; }