http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1081
题目大意:给定一个点数为 n 的多边形,点按照顺序给出,再给出 m 个点,询问每个点是否在多边形内。
——————————————————————————————
计算几何开荒期,所以都算是板子吧……既然是板子那么题解自然也都是集网上之大成。
所以以后也就不多说了。正式往下看题解吧。
——————————————————————————————
这是一道求点是否在一个多边形内的题。
对这道题我们有两种算法,第二种太麻烦了就不讲了。
第一种为射线法:即我们有一个点,向左(右)水平做一道射线,求出射线与四边形交点个数,如果个数为奇数则在这里面。
但是如果交在线段端点上时我们需要规定交在边的下端点统计进答案或是交在边的上端点统计进答案(也就是保证一个点要么都被统计要么都不被统计)。
判断端点序号的坐标上下关系用叉乘,顺便可以判断该点是否在边上。
#include<cstdio> #include<queue> #include<cctype> #include<cstring> #include<vector> #include<algorithm> using namespace std; typedef long long ll; const int M=500010; const int N=1000010; const int INF=10*N; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct point{//既是向量又是点 int x; int y; }q[N],p; int n,m,cnt; inline point getmag(point a,point b){ point s; s.x=b.x-a.x;s.y=b.y-a.y; return s; } inline int multiX(point a,point b){ return a.x*b.y-b.x*a.y; } inline int multiP(point a,point b){ return a.x*b.x+a.y*b.y; } bool pan(){ int sum=0; for(int i=1;i<=n;i++){ int d=multiX(getmag(p,q[i]),getmag(p,q[i%n+1])); if(!d){//三点共线 if(multiP(getmag(p,q[i]),getmag(p,q[i%n+1]))<=0)return 1;//是否在线段上 } int d1=q[i].y-p.y; int d2=q[i%n+1].y-p.y; if(d>0&&d1>=0&&d2<0)sum++; if(d<0&&d1<0&&d2>=0)sum++; } if(sum%2)return 1; return 0; } int main(){ while(scanf("%d",&n)!=EOF&&n){ m=read(); cnt++; if(cnt!=1)putchar(' '); for(int i=1;i<=n;i++){ q[i].x=read(); q[i].y=read(); } printf("Problem %d: ",cnt); for(int i=1;i<=m;i++){ p.x=read(); p.y=read(); if(pan())puts("Within"); else puts("Outside"); } } return 0; }