1. 程式人生 > >ZOJ 1081 Within(點是否在多邊形內)| 計算幾何

ZOJ 1081 Within(點是否在多邊形內)| 計算幾何

tps 不能 per ges sin else 出發 getchar() .cn

ZOJ 1081 Within

我使用的是“射線法”:從該點出發,作一條向左的水平射線,與多邊形的邊的交點有奇數個則點在多邊形內。

需要註意的點:

  1. 如果點在多邊形的邊上特判。
  2. 考慮射線與多邊形的一個交點是多邊形的頂點的情況,
    技術分享圖片
    最左邊的那個頂點算一個交點,左邊第二種的那個頂點算兩個交點或不算交點都行(但不能算一個交點)。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long
ll; template <class T> void read(T &x){ char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'
; if(op) x = -x; } template <class T> void write(T x){ if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 105; int n, m; struct point { int x, y; point(){} point(int _x, int _y): x(_x), y(_y){} point operator
- (point b){ return point(x - b.x, y - b.y); } int operator * (point b){ // 這是叉乘 return x * b.y - y * b.x; } int operator % (point b){ // 這是點乘 return x * b.x + y * b.y; } }; bool bel(point p, point u, point v){ if((u - p) * (v - p)) return 0; return (u - p) % (v - p) <= 0; } struct poly { point p[N]; bool includ(point q){ int cnt = 0; for(int i = 1; i <= n; i++){ if(bel(q, p[i], p[i + 1])) return 1; int d1 = q.y - p[i].y, d2 = q.y - p[i + 1].y; int det = (p[i] - q) * (p[i + 1] - q); if((det >= 0 && d1 < 0 && d2 >= 0) || (det <= 0 && d2 < 0 && d1 >= 0)) cnt++; } return cnt & 1; } } P; int main(){ int T = 0, u, v; while(read(n), n){ if(T) puts(""); printf("Problem %d:\n", ++T); read(m), read(u), read(v); P.p[1] = P.p[n + 1] = (point){u, v}; for(int i = 2; i <= n; i++){ read(u), read(v); P.p[i] = (point){u, v}; } while(m--){ read(u), read(v); if(P.includ((point){u, v})) puts("Within"); else puts("Outside"); } } return 0; }

ZOJ 1081 Within(點是否在多邊形內)| 計算幾何