ZOJ1081:Points Within——題解

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1081git

題目大意:給定一個點數爲 n 的多邊形,點按照順序給出,再給出 m 個點,詢問每一個點是否在多邊形內。算法

——————————————————————————————ide

計算幾何開荒期,因此都算是板子吧……既然是板子那麼題解天然也都是集網上之大成。spa

因此之後也就很少說了。正式往下看題解吧。code

——————————————————————————————blog

這是一道求點是否在一個多邊形內的題。get

對這道題咱們有兩種算法,第二種太麻煩了就不講了。string

第一種爲射線法:即咱們有一個點,向左(右)水平作一道射線,求出射線與四邊形交點個數,若是個數爲奇數則在這裏面。it

可是若是交在線段端點上時咱們須要規定交在邊的下端點統計進答案或是交在邊的上端點統計進答案(也就是保證一個點要麼都被統計要麼都不被統計)。io

判斷端點序號的座標上下關係用叉乘,順即可以判斷該點是否在邊上。

#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;
}
相關文章
相關標籤/搜索