题解
- 参考蓝书
- 先判断两个凸包是否相交
- 其次判断某个凸包的点是否在另一个里面
- 凸包退换成点和线段其实不影响
代码
#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;
}