题目:传送门
题意:给你一个圆和一个多边形, 判断多边形是不是凸多边形,如果是,接着判断圆是否在凸多边形内部。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> #define LL long long #define mem(i, j) memset(i, j, sizeof(i)) #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define pb push_back #define make make_pair #define INF INT_MAX #define inf LLONG_MAX #define PI acos(-1) using namespace std; struct Point{ double x, y; Point(double x = 0, double y = 0) : x(x), y(y) { } }; const int N = 110; const double eps = 1e-8; int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } Point operator + (Point A, Point B) { return Point(A.x + B.x, A.y + B.y); } Point operator - (Point A, Point B) { return Point(A.x - B.x, A.y - B.y); } Point operator * (Point A, double p) { return Point(A.x * p, A.y * p); } Point operator / (Point A, double p) { return Point(A.x / p, A.y / p); } bool operator == (Point A, 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(Dot(A, A)); } bool Onseg(Point p, Point a1, Point a2) { /// 判断点 p 是否在线段 a1a2 上(含端点) return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) <= 0; } bool SPI(Point a1, Point a2, Point b1, Point b2) { /// 判断线段a1a2与线段b1b2是否相交 return max(a1.x,a2.x) >= min(b1.x,b2.x) && max(b1.x,b2.x) >= min(a1.x,a2.x) && max(a1.y,a2.y) >= min(b1.y,b2.y) && max(b1.y,b2.y) >= min(a1.y,a2.y) && dcmp(Cross(b1 - a2, a1 - a2)) * dcmp(Cross(b2 - a2, a1 - a2)) <= 0 && dcmp(Cross(a1 - b2, b1 - b2)) * dcmp(Cross(a2 - b2, b1 - b2)) <= 0; } inline int isPointInpolygon(Point tmp, Point P[], int n) { /// 判断点是否在多边形里 int wn = 0; rep(i, 0, n - 1) { if(Onseg(tmp, P[i], P[(i + 1) % n])) return -1; /// 边界 int k = dcmp(Cross(P[(i + 1) % n] - P[i], tmp - P[i])); int d1 = dcmp(P[i].y - tmp.y); int d2 = dcmp(P[(i +1) % n].y - tmp.y); if(k > 0 && d1 <= 0 && d2 > 0) wn++; if(k < 0 && d2 <= 0 && d1 > 0) wn--; } if(wn != 0) return 1; /// 内部 return 0; /// 外部 } /// 判断凸多边形,允许共线,点可以是顺时针给出也可以是逆时针给出,编号0~n-1 bool isconvex(Point p[], int n) { bool vis[3]; mem(vis, 0); rep(i, 0, n - 1) { vis[dcmp(Cross(p[(i + 1) % n] - p[i], p[(i + 2) % n] - p[i])) + 1] = 1; if(vis[0] && vis[2]) return false; } return true; } double DistanceToSegment(Point p, Point A, Point B) { /// 求点 p 到线段 AB 的最短距离 if(A == B) return Length(p - A); Point v1 = B - A, v2 = p - A, 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); } Point P[N]; int main() { int n; double R, x, y; while(scanf("%d", &n) == 1) { if(n < 3) break; scanf("%lf %lf %lf", &R, &x, &y); rep(i, 0, n - 1) scanf("%lf %lf", &P[i].x, &P[i].y); if(!isconvex(P, n)) { /// 不是凸多边形 puts("HOLE IS ILL-FORMED"); continue; } Point p = Point(x, y); if(isPointInpolygon(p, P, n) == 0) { /// 点不在多边形内部 puts("PEG WILL NOT FIT"); continue; } bool flag = 0; rep(i, 0, n - 1) { /// 判断点到线段的最短距离是否大于等于 R if(dcmp(fabs(DistanceToSegment(p, P[i], P[(i + 1) % n])) - R) < 0) { flag = 1; break; } } if(flag) puts("PEG WILL NOT FIT"); else puts("PEG WILL FIT"); } return 0; }
原文地址:https://www.cnblogs.com/Willems/p/12401486.html
时间: 2024-11-05 18:52:20