ZOJ1081(射线法判断点是否在多边形内部)

通往快乐老家的路

射线法判是否在多边形内部的板子吧

射线法:过该点做一条平行于x轴的射线 ,若该与多边形有奇数个交点,则该点在多边形内部

这可以转化为求改点与多边形的每一条边是否有交点

但要注意一些特殊情况,比如交点时多边形的顶点,这时我们需要规定交在边的下端点 统计进答案或是交在边的上端点统计进答案

(也就是保证一个点要么都被统计要么都不被统 计)。

详解代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res*f;
}
struct point{
	int x,y;
	point(){}
	point(int a,int b):
		x(a),y(b){}
	friend inline point operator -(const point &a,const point &b){//重载运算符 
		return point(b.x-a.x,b.y-a.y);
	}
	friend inline int operator *(const point &a,const point &b){
		return a.x*b.y-a.y*b.x;
	}
	friend inline int dot(const point &a,const point &b){//点积 
		return a.x*b.x+a.y*b.y;	
	}
}f,p[105];
inline bool check(const point &a,const point &b,const point &c){//判断共线的情况 (三点共线且被判定的点在线段中间) 
	int d=(a-c)*(b-c);
	if(d!=0) return false;//如果差积不为0,则三点不共线 
	int fk=dot(a-c,b-c);
	return fk<=0;//如果点积大于0,则被判定的点不在线段中间 
}
inline int area(){//求多边形的面积 
	int ans=0;
	for(int i=0;i<n;i++){
		ans+=p[i]*p[i+1];
	}
	return ans;
}
inline bool init(point q){
	int num=0;
	for(int i=0;i<n;i++){//枚举找相交的边 
		if(check(p[i],p[i+1],q)) return true;//如果在线段之间则满足 
		int f1=p[i].y-q.y,f2=p[i+1].y-q.y;
		int det=(p[i]-q)*(p[i+1]-q);
		if((det>=0&&f1<0&&f2>=0)||(det<=0&&f1>=0&&f2<0)) num++;//这里默认的是做一条平行于x轴的射线,并判断有没有交点 
	}
	return num&1;//相交的边数是否为奇数 
}
int main(){
	for(int T=1;;T++){
		n=read();
		if(n==0) break;
		m=read();
		for(int i=0;i<n;i++){
			p[i].x=read(),p[i].y=read();
		}
		p[n]=p[0];
		if(T!=1){
			cout<<'\n';
		}
		cout<<"Problem "<<T<<":"<<'\n';
		for(int i=1;i<=m;i++){
			f.x=read(),f.y=read();	
			if(init(f)) cout<<"Within"<<'\n';
			else cout<<"Outside"<<'\n';
			
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/83056755