謝勇大神畫了張圖,然後這個問題就解決了。。。
本質是“半平面交”問題。
直線切割多邊形,公用的部分就是多邊形的核
這裡找到一個不錯的模板:
http://blog.csdn.net/accry/article/details/6070621
http://blog.csdn.net/candy20094369/article/details/6703940
#include <iostream>#include <cstdio>#include <cmath>#include <vector>#include <cstring>#include <algorithm>#include <string>#include <set>#include <ctime>#define CL(arr, val) memset(arr, val, sizeof(arr))#define REP(i, n) for((i) = 0; (i) < (n); ++(i))#define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i))#define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i))#define L(x) (x) << 1#define R(x) (x) << 1 | 1#define MID(l, r) (l + r) >> 1#define Min(x, y) x < y ? x : y#define Max(x, y) x < y ? y : x#define E(x) (1 << (x))const double eps = 1e-8;typedef long long LL;using namespace std;const int maxn = 110;struct Point { double x; double y; Point(double a = 0, double b = 0): x(a), y(b) {} void input() { scanf("%lf%lf", &x, &y); }};Point point[maxn], p[maxn], q[maxn]; //讀入的多邊形的頂點(順時針)、p為存放最終切割得到的多邊形頂點的數組、暫存核的頂點 int cCnt, n; //此時cCnt為最終切割得到的多邊形的頂點數、暫存頂點個數inline int dbcmp(double x) { //精度問題 if(x > eps) return 1; else if(x < -eps) return -1; return 0;}inline void getline(Point x, Point y, double& a, double& b, double& c) { //點X,Y確定一條直線 a = y.y - x.y; b = x.x - y.x; c = y.x*x.y - x.x*y.y;}inline Point intersect(Point x, Point y, double a, double b, double c) { ////求x、y形成的直線與已知直線a、b、c、的交點 double u = fabs(a*x.x + b*x.y + c); double v = fabs(a*y.x + b*y.y + c); return Point((x.x*v + y.x*u)/(u + v), (x.y*v + y.y*u)/(u + v));}inline void cut(double a, double b, double c) { //如所示,切割 int cur = 0, i; for(i = 1; i <= cCnt; ++i) { if(dbcmp(a*p[i].x + b*p[i].y + c) >= 0) q[++cur] = p[i]; // c由於精度問題,可能會偏小,所以有些點本應在右側而沒在 else { if(dbcmp(a*p[i-1].x + b*p[i-1].y + c) > 0) //如果p[i-1]在直線的右側的話, //則將p[i],p[i-1]形成的直線與已知直線的交點作為核的一個頂點(這樣的話,由於精度的問題,核的面積可能會有所減少) q[++cur] = intersect(p[i], p[i-1], a, b, c); if(dbcmp(a*p[i+1].x + b*p[i+1].y + c) > 0) q[++cur] = intersect(p[i], p[i+1], a, b, c); } } for(i = 1; i <= cur; ++i) p[i] = q[i]; p[cur+1] = q[1]; p[0] = p[cur]; cCnt = cur;}void solve() { //注意:預設點是順時針,如果題目不是順時針,規整化方向 int i; for(i = 1; i <= n; ++i) { double a, b, c; getline(point[i], point[i+1], a, b, c); cut(a, b, c); } if(cCnt == 0) puts("NO"); else puts("YES");}void init() { int i; FOR(i, 1, n) point[i].input(); point[n+1] = point[1]; //初始化p[], cCnt FOR(i, 1, n) p[i] = point[i]; p[n+1] = p[1]; p[0] = p[n]; cCnt = n;}int main() { //freopen("data.in", "r", stdin); int t; scanf("%d", &t); while(t--) { scanf("%d", &n); init(); solve(); } return 0;}