自我感觉这道题难的是题意,别的其实不难!当时看到这道题,看了一遍,觉得难懂,然后就做下面的题了,然后又回过头来看题还是一知半解,然后看了别人的翻译的大致题意,结果还是错理解了,题中是允许多点共线的!
大致思路:首先对于所给的洞的点,判断是否是凸多边形,图形的输入和输出可以是顺时针或者逆时针,而且允许多点共线,这点让我WA了一次!
判断是凸多边形后,判断所给的圆心是否在多边形内,然后判断圆心到各边的距离是否大于半径,以此就可以得到结果了!
#include<iostream>//注意是允许有共线的情况的 #include<cmath> #include<cstdio> using namespace std; #define exp 0.0000000001 typedef struct point { double x,y; }rr; point a[10000],b; double radius,pegx,pegy; int n; double multipy(point p1,point p2,point p3,point p4) { double s=(p2.x-p1.x)*(p4.y-p3.y)-(p2.y-p1.y)*(p4.x-p3.x); return s; } double dis(point p1,point p2) { if(fabs(p1.x-p2.x)<exp)//相等的 { return fabs(p2.x-pegx); } else { double k=(p2.y-p1.y)/(p2.x-p1.x); double b=p2.y-k*p2.x; return fabs(k*pegx-pegy+b)/sqrt(k*k+1);//返回的是距离的 } } int main() { while(true) { scanf("%d",&n); int i; if(n<3) break; scanf("%lf%lf%lf",&radius,&pegx,&pegy); for(i=0; i<n; i++) scanf("%lf%lf",&a[i].x,&a[i].y); a[n].x=a[0].x;a[n].y=a[0].y; a[1+n].x=a[1].x;a[n+1].y=a[1].y;//要对所有的角都进行测试的 int sign=0; i=3; int t=0;//表死有三点共线的情况的 for(i=3; i<=n+1; i++) { if(multipy(a[i-2],a[i-1],a[i-1],a[i])>exp)//首先第一个测试,是判定给出的点是顺时针给的还是逆时针给的 { t=1;//正的 break; } if(multipy(a[i-2],a[i-1],a[i-1],a[i])<-exp) { t=2;//负的 break; } } if(t!=0) { for(;i<=n+1; i++) { if((t==1 && multipy(a[i-2],a[i-1],a[i-1],a[i])<-exp) || (t==2 && multipy(a[i-2],a[i-1],a[i-1],a[i])>exp))//在逆时针的地方,就是错的 { sign=1; break; } } } if(sign==1 || t==0) printf("HOLE IS ILL-FORMED\n"); else { //先判断是否在内部的 b.x=pegx;b.y=pegy; for(i=1; i<=n; i++) if((t==1 && multipy(a[i-1],a[i],a[i],b)<=exp) || (t==2 && multipy(a[i-1],a[i],a[i],b)>=-exp)) { sign=1; break; } if(sign==0) { for(i=0; i<n; i++) { double len=dis(a[i],a[i+1]); if(len<radius)//小于0 { sign=1;//即不能发下钉子的 break; } } } if(sign==1) printf("PEG WILL NOT FIT\n"); else printf("PEG WILL FIT\n"); } } return 0; }