模板题。
原理:先判点是不是在线段上。然后从这个点任意做一条射线,若与奇数条边相交,则该点在圆内,否则该点在圆外,注意遇到多边形的两条边的交点,算相交一次。
我们可以定义线段为左闭右开区间,这样可以避免重复计算。
这题比较特殊,dotOnSeg这个函数也特殊化了,不过point_in_polygon这个没有特殊化,只要改一下dotOnSeg就可以解决这类问题了。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct point { int x, y; void in() { scanf("%d%d", &x, &y); } }l[20004], r[20004], o; int n; bool dotOnSeg(point o, point s, point e) { if(s.x == o.x && e.x == o.x && o.y >= min(s.y, e.y) && o.y <= max(s.y, e.y)) return 1; if(s.y == o.y && e.y == o.y && o.x >= min(s.x, e.x) && o.x <= max(s.x, e.x)) return 1; return 0; } int cross(point o, point a, point b) { return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x); } int point_in_polygon() { // 点是否在多边形内, 2边上,1内部,0外部 int i, t; point a, b; for (i=0; i < n; i++) { if ( dotOnSeg(o, l[i], r[i]) ) return 2; } t = 0; for (i=0; i < n; i++) { a = l[i]; b = r[i]; if ( a.y > b.y ) { point tmp = a; a = b; b = tmp; } if ( cross(o, a, b) < 0 && a.y <= o.y && o.y < b.y ) t++; } return t&1; } int main() { int i, j; scanf("%d", &n); for(i = 0; i < n; i++) l[i].in(), r[i].in(); o.in(); int g = point_in_polygon(); if(g == 1) puts("INSIDE"); else if(g == 2) puts("BORDER"); else puts("OUTSIDE"); return 0; }