Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 4475 | Accepted: 1374 |
Description
Input
Output
Sample Input
5 1.5 1.5 2.0 1.0 1.0 2.0 2.0 1.75 2.0 1.0 3.0 0.0 2.0 5 1.5 1.5 2.0 1.0 1.0 2.0 2.0 1.75 2.5 1.0 3.0 0.0 2.0 1
Sample Output
HOLE IS ILL-FORMED PEG WILL NOT FIT
Source
/*************************************************** Accepted 192 KB 0 ms C++ 4208 B 2013-07-28 16:02:24 题意:给你一个含有 N个点的多边形和一个钉子 判断钉子是否在多边形内部 注意:输入的第一行先输入多边形的点数, 再输入的是钉子的半径,然后才是坐标ToT 思路:1.先判断多边形是不是凸多边形, 如果不是,则输出 HOLE IS ILL-FORMED 如果是,则继续往下判断 2.(1)判断圆心是否在凸多边形外面 如果在外面,直接返回 false 如果在边上,而且半径 == 0,返回 true 半径不为 0 , 返回 false 如果在内部,则遍历圆心到每一条边线段的距离是否 >= 半径 如果全部满足,则返回 true 否则返回 false 如果钉子能装下,则输出PEG WILL FIT 否则输出PEG WILL NOT FIT ***************************************************/ #include<stdio.h> #include<math.h> const int maxn = 200; struct Point{ double x,y; Point() {} Point(double _x, double _y) { x = _x; y = _y; } Point operator - (const Point &B) { return Point(x-B.x, y-B.y); } }p[maxn]; struct Circle{ Point center; double radius; }c; const double eps = 1e-5; int dcmp(double x) { if(fabs(x) < 0) return 0; else return x < 0 ? -1 : 1; } bool operator == (const Point &A, const Point &B) { return dcmp(A.x-B.x)== 0 && dcmp(A.y-B.y) == 0; } double Cross(Point A, Point B) /** 叉积*/ { return A.x*B.y - A.y*B.x; } double Dot(Point A, Point B) /** 点积*/ { return A.x*B.x+A.y*B.y; } double Length(Point A) { return sqrt(A.x*A.x + A.y*A.y); } /** 判断多边形是否是凸多边形【含共线】*/ bool isConvex(Point *p, int n) { p[n] = p[0]; // 边界处理 p[n+1] = p[1]; // 注意也可以用 %n 处理, 下标从 0 开始 int now = dcmp(Cross(p[1]-p[0], p[2]-p[1])); for(int i = 1; i < n; i++) { int next = dcmp(Cross(p[i+1]-p[i], p[i+2]-p[i+1])); if(now*next < 0) //此处可以共线 { return false; } now = next; //注意记录临界条件 } return true; } /** 点Point 是否在有 n 个顶点的凸多边形内【含边界】*/ int isPointInConvex(Point *p, int n, Point point) { int flag = 1; p[n] = p[0]; int now = dcmp(Cross(p[0]-point, p[1]-point)); for(int i = 1; i < n; i++) { int next = dcmp(Cross(p[i]-point, p[i+1]-point)); if(next*now < 0) { return -1; /** 点在外面*/ } else if(next*now == 0) { return 0; /** 点在边上 */ } now = next; } return flag; /** 点在内部*/ } /** 判断点P 到线段 AB的距离*/ double DistanceToSegment(Point P, Point A, Point B) { if(A == B) return Length(P-A); Point v1 = B-A; Point v2 = P-A; Point v3 = P-B; if(dcmp(Dot(v1, v2)) < 0) return Length(v2); else if(dcmp(Dot(v1, v3)) > 0) return Length(v3); else return fabs(Cross(v1, v2))/ Length(v1); //忠告:不要脑残的 / 2... } /** 判断圆是否在凸多边形内部, 相切也可以*/ bool isCircleInConvex(Point *p, int n, Circle c) { int flag = isPointInConvex(p, n, c.center); /**判断圆心*/ if(flag == 0) /** 圆心在边上*/ { if(c.radius == 0) return true; else return false; } else if(flag == 1) /** 圆心在内部*/ { p[n] = p[0]; /** 边界处理*/ for(int i = 0; i < n; i++) /** 遍历所有的边 */ { if(dcmp(DistanceToSegment(c.center, p[i], p[i+1])-c.radius) < 0) { return false; } } return true; } else return false; /** 圆心在外部*/ } int main() { int n; while(scanf("%d", &n) != EOF) { if(n < 3) break; /** 忠告:输入时注意顺序, 不要脑残。。。*/ scanf("%lf%lf%lf", &c.radius, &c.center.x, &c.center.y); for(int i = 0; i < n; i++) scanf("%lf%lf", &p[i].x, &p[i].y); bool flag = isConvex(p, n); /** 判断是否是凸多边形*/ if(flag) { flag = isCircleInConvex(p, n, c); if(flag) printf("PEG WILL FIT\n"); else printf("PEG WILL NOT FIT\n"); } else printf("HOLE IS ILL-FORMED\n"); } return 0; }