1. 程式人生 > >ZOJ1081:Points Within——題解

ZOJ1081:Points Within——題解

!= clu typedef const log 既然 inline cstring n)

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(\n); for(int i=1;i<=n;i++){ q[i].x=read(); q[i].y=read(); } printf("Problem %d:\n",cnt); for(int i=1;i<=m;i++){ p.x=read(); p.y=read(); if(pan())puts("Within"); else puts("Outside"); } } return 0; }

ZOJ1081:Points Within——題解