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;
}
相关文章
相关标签/搜索