题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
题目给出一个多边形,然后给出一个点,需要判断该点与多边形的关系:
IN 2 //在多边形内
ON 1 //在多边形边上
OUT 0//在多边形内部
基本思路是,
先判断这个点是不是在多变形的边上,用类似于ccw的方法来判断;
从这个点发出一条沿x轴方向的射线,射向这个多边形:
如果这条射线和这个多边形的交点个数为偶数,则说明该点在多边形外部;
如果这条射线和这个多边形的交点个数为奇数,则说明该店在多边形内部;
核心代码是这样:
int contains(Polygon g, Point p) {
int n = g.size();
bool x = false;
for (int i = 0; i < n; i++) {
Point a = g[i] - p, b = g[(i + 1) % n] - p;
if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
if (a.y > b.y) swap(a, b);
if (a.y < EPS && EPS < b.y && cross(a, b) > EPS)
x = !x;
}
return (x ? 2 : 0);
}
我们在代码中,这样来实现发出射线这个过程:
遍历这个多边形的每两个相邻的点,g[n]和g[n+1],和p点,先判断是否p点在g[n]和g[n+1]线段上,是的话直接return 1;
然后判断射线是否经过了这条线段:
以点p为原点,指向g[n]的向量为a,指向g[n+1]的向量为b;如果这两个向量一个在x轴上部,一个在y轴下部,那么就说明从点p发出的与x轴平行的射线是可以穿过这条线段的;
实现部分代码如下:
int main(){
Polygon g;
Point p ,t;
int n, q;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%lf %lf", &t.x, &t.y);
g.push_back(t);
}
cin>>q;
for (int i = 0; i < q; i++) {
cin>>p.x>>p.y;
cout<<contains(g, p)<<endl;
}
return 0;
}
错点:
1.在判断a和b是否一个在x轴上方,一个在x轴下方时,先选出一个y值较大的为a;然后在判断时,要注意
if (a.y < EPS && EPS < b.y && cross(a, b) > EPS) 要加上 cross(a, b) > EPS 避免出现三点共线,但是p点不在线段上的情况;