boj 35 Video Surveillance 半平面交求多邊形的核
阿新 • • 發佈:2019-01-22
//============================================================================ // Name : 35.cpp // Author : wly // Version : // Copyright : Your copyright notice // Description : Video Surveillance // Algorithm : 求多邊形的核 // 計算幾何,半平面交求多邊形的核 // http://blog.csdn.net/accry/article/details/6070621 // 半平面交找核思想: // 對多邊形的每一條邊,這條邊所在的直線都可以將平面分成兩塊,求一條邊劃分的半平面與之前得出的多邊形的交, // 得出的多邊形再與下一條邊的半平面求交,依次類推,最後得到的多邊形就是原多邊形的核 //============================================================================ #include <stdio.h> #include <stdlib.h> #include <cmath> #include <algorithm> using namespace std; const double MAX = 100000000; const double pi = acos(-1.0); const double eps = 1e-8; int cCnt, curCnt, n; //點結構 struct Point { double x, y; Point(double ix, double iy) : x(ix), y(iy) { } Point() { } void input() { scanf("%lf%lf", &x, &y); } } points[110], p[110], q[110]; //將兩點確定的直線量化 inline void getline(Point x, Point y, double &a, double &b, double &c) { a = y.y - x.y; b = x.x - y.x; c = y.x * x.y - x.x * y.y; } int sig(double k) { return (k < -eps) ? -1 : (k > eps); } //x點y點的連線與量化後的直線求交點 void interect(Point x, Point y, double a, double b, double c) { double u = fabs(a * x.x + b * x.y + c); double v = fabs(a * y.x + b * y.y + c); q[++curCnt].x = (x.x * v + y.x * u) / (u + v); q[curCnt].y = (x.y * v + y.y * u) / (u + v); } //利用半平面切割 void cut(double a, double b, double c) { curCnt = 0; int i; for (i = 1; i <= cCnt; i++) //遍歷所有頂點是否能觀察到該邊 { if (sig(a * p[i].x + b * p[i].y + c) >= 0)//因為線段是順時針給出的,如果是逆時針就是<=0 { q[++curCnt] = p[i]; //若是則儲存 } else { if (sig(a * p[i - 1].x + b * p[i - 1].y + c) > 0)//逆時針就是<0 interect(p[i - 1], p[i], a, b, c); if (sig(a * p[i + 1].x + b * p[i + 1].y + c) > 0)//逆時針就是<0 interect(p[i + 1], p[i], a, b, c); } } //最後的p陣列存放半平面的點集合 for (i = 1; i <= curCnt; i++) p[i] = q[i]; p[curCnt + 1] = p[1], p[0] = p[curCnt]; cCnt = curCnt; } //半平面交初始化 inline void initial() { for (int i = 1; i <= n; ++i) p[i] = points[i]; points[n + 1] = points[1]; p[n + 1] = p[1]; p[0] = p[n]; cCnt = n; } //輸入 inline void init() { for (int i = 1; i <= n; i++) points[i].input(); } //獲得多邊形的核,結果存在p陣列中,如果沒有結果,p陣列長度為0 inline void solve() { initial(); for (int i = 1; i <= n; ++i) { double a, b, c; getline(points[i], points[i + 1], a, b, c); cut(a, b, c); } //多邊形核的面積 /*double area = 0; for (int i = 1; i <= curCnt; ++i) area += p[i].x * p[i + 1].y - p[i + 1].x * p[i].y; area = fabs(area / 2.0);*/ } int main() { int tc = 1; while (scanf("%d", &n), n) { init(); solve(); printf("Floor #%d\n", tc++); if (!cCnt) puts("Surveillance is impossible.");//這裡如果有一個點,或者一條線段都可以,所以判斷m是不是等於0就行了,不用判斷面積 else puts("Surveillance is possible."); printf("\n"); } return 0; }