1015 - 计算几何之点与多边形的关系 - Points Within(ZOJ1081)

版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/83057291

传送门

分析

射线法

虽然这个射线法有很多需要特判的情况,但总的来说还是蛮好用的

判断点与多边形的关系,若使用射线法,就是说从这个点往右做一条与 x 轴平行的射线,看它与多边形相交了几次

若相交了偶数次,则不在多边形内部(相当于从这个多边形中穿过去,没有留在里面)

若相交了奇数次,则在多边形内部

1.要特殊考虑一下这种情况

若刚好穿过一个点,照我们的方法,会被计算两次(上面的边一次,下面的边一次),而这明显不对

所以我们就要强制规定,经过一条边的左端点(或右端点)才能被计算

2.如果这个点刚好落在多边形的边上,(由于这道题我们是把这种情况当做落在里面)我们需要判断一下

3.由于射线法是往一个方向延伸,所以当一条边一条边的加入,边转到这个点的左边(或右边)时,就不能纳入计数了

在代码中实现就是这样的:
 

int d1=a[i].y-b.y;int d2=a[j].y-b.y;
if((det>=0&&d1<0&&d2>=0)||(det<=0&&d1>=0&&d2<0)) cnt++;

d1记录 i 这个顶点与 b 纵坐标之差,d2记录下一个 i+1 这个顶点与 b 的纵坐标之差。

代码

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-7;
struct point{
	int x,y;
	point (int _x=0.0,int _y=0.0):x(_x),y(_y){} 
	friend inline point operator +(const point &a,const point &b){
		return point(a.x+b.x,a.y+b.y);
	}
	friend inline point operator -(const point &a,const point &b){
		return point(a.x-b.x,a.y-b.y);
	}
	friend inline point operator *(double k,const point &a){
		return point(k*a.x,k*a.y);
	}
	friend inline int dot(const point &a,const point &b){
		return (a.x*b.x+a.y*b.y);
	}
	friend inline int cross(const point &a,const point &b){
		return (a.x*b.y-b.x*a.y);
	}
	friend inline double len(const point &a){
		return sqrt(dot(a,a));
	}
	friend inline double dis (const point &a,const point &b){
		return len(a-b);
	}//向量常见的运算 
}a[105],b;
int n,m;
bool check(){
	int cnt=0;
	for(int i=1;i<=n;++i){
		int j=i+1;
		if(j>n) j=1;
		int det=cross(a[i]-b,a[j]-b);
		if(det==0)	if(dot(a[i]-b,a[j]-b)<=0) return 1;
		int d1=a[i].y-b.y;int d2=a[j].y-b.y;
		if((det>=0&&d1<0&&d2>=0)||(det<=0&&d1>=0&&d2<0)) cnt++;
	}
	return cnt&1;
}
int main(){
	for(int tt=1;;tt++){
		scanf("%d",&n);
		if(n==0) break;
		scanf("%d",&m);
		int i,j,k;
		for(i=1;i<=n;++i)
			scanf("%d%d",&a[i].x,&a[i].y);
		if(tt!=1) printf("\n");
		printf("Problem %d:\n",tt);	
		for(i=1;i<=m;++i){
			scanf("%d%d",&b.x,&b.y);
			if(check()) printf("Within\n");
			else printf("Outside\n");
		}
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/83057291