UVA10256:点在多边形内判断 + 凸包

UVA10256

题解

  • 参考蓝书
  • 先判断两个凸包是否相交
  • 其次判断某个凸包的点是否在另一个里面
  • 凸包退换成点和线段其实不影响

代码

#include <bits/stdc++.h>
using namespace std;
int const N = 1000 + 10;
const double eps = 1e-10;
int n,m;
int dcmp(double x){    //判断符号
	if(fabs(x) < eps)	return 0;
	else return x < 0 ? -1 : 1;
}
typedef struct Point{   //点和向量
	double x,y;
	Point(){};
	Point(double x,double y):x(x),y(y){};
	Point operator - (const Point& e)const{   //减
		return Point(x - e.x,y - e.y);
	}
	double operator ^ (const Point& e)const{  //叉乘
		return x * e.y - y * e.x;
	}
	bool operator < (const Point& e)const{  //比较
		return x < e.x || x == e.x && y < e.y;
	}
	bool operator == (const Point &e)const{  //相等
		return !dcmp(x - e.x) && !dcmp(y - e.y);
	}
}Vector;
Point pn[N],pm[N],chn[N],chm[N];
double Dot(Vector a,Vector b){
	return a.x * b.x + a.y * b.y;
}
//非规范相交
bool onsegment(Point p,Point a1,Point a2){ //点p是否在线段a1a2上,端点不重合。如果否则取等号,则端点可以重合。
	return dcmp((a1 - p) ^ (a2 - p)) == 0 && dcmp(Dot(a1 - p,a2 - p)) < 0;  
}
//规范相交
bool SegmentProperIntersection1(Point a1, Point a2, Point b1, Point b2)
{
	double c1 = (a2 - a1) ^ (b1 - a1), c2 = (a2 - a1) ^ (b2 - a1);
	double c3 = (b2 - b1) ^ (a1 - b1), c4 = (b2 - b1) ^ (a2 - b1);
	return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
}
bool SegmentProperIntersection2(Point a1,Point a2,Point b1,Point b2){   //线段a1a2和线段b1b2
    if(SegmentProperIntersection1(a1,a2,b1,b2))	return true;
    return false;
}
int ConvexHull(Point *p,int n,Point* ch){ //Andrew算法求凸包
	sort(p,p+n);
	int m = 0;
	for(int i=0;i<n;i++){
		while(m > 1 && ((ch[m-1] - ch[m-2]) ^ (p[i] - ch[m-2])) <= 0)	m--;
		ch[m++] = p[i];
	}
	int k = m;
	for(int i=n-2;i>=0;i--){
		while(m > k && ((ch[m-1] - ch[m-2]) ^ (p[i] - ch[m-2])) <= 0)	m--;
		ch[m++] = p[i];
	}
	if(n > 1)	m--;
	return m;
}
bool isPointInPolygon(Point p,Point *poly,int n){   //判断点是否在凸多边形内部
	for(int i=0;i<n;i++){
		double c1 = (poly[i] - poly[(i+1)%n]) ^ (p - poly[(i+1)%n]);
		double c2 = (poly[(i+2)%n] - poly[(i+1)%n]) ^ (p - poly[(i+1)%n]);
		if(dcmp(c1) * dcmp(c2) >= 0)	return false;   //等号表示点在多边形的边上
	}
	return true;
}
bool solve(Point* pn,int n,Point* pm,int m){
	for(int i=0;i<n;i++){   //线段相交
		for(int j=0;j<m;j++){
			if(SegmentProperIntersection2(pn[i],pn[(i+1)%n],pm[j],pm[(j+1)%m]))	return false;
		}
	}
	for(int i=0;i<n;i++)	if(isPointInPolygon(pn[i],pm,m))	return false;
	for(int i=0;i<m;i++)	if(isPointInPolygon(pm[i],pn,n))	return false;	
	return true;
}
int main(){
	while(~scanf("%d%d",&n,&m) && (n || m)){
		for(int i=0;i<n;i++)
			scanf("%lf%lf",&pn[i].x,&pn[i].y);
		for(int i=0;i<m;i++)
			scanf("%lf%lf",&pm[i].x,&pm[i].y);
		int tn = ConvexHull(pn,n,chn);
		int tm = ConvexHull(pm,m,chm);
		if(solve(chn,tn,chm,tm))	printf("Yes\n");
		else	printf("No\n");
	}
	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/weixin_42264485/article/details/89060258