标签:
题意:给定两个点集,一个红点集,另一个蓝点集,询问,能否找到一条直线能,使得任取一个红点和蓝点都在直线异侧。
思路:划分成两个凸包,一个红包,一个蓝包。两个凸包不相交不重合。
1.任取一个凸包中的点不在另一个凸包中。
2.任取一个凸包中的边与另一个凸包不相交。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 #include<memory.h> 7 #include<cstdlib> 8 #include<vector> 9 #define clc(a,b) memset(a,b,sizeof(a)) 10 #define LL long long int 11 #define up(i,x,y) for(i=x;i<=y;i++) 12 #define w(a) while(a) 13 using namespace std; 14 const double inf=0x3f3f3f3f; 15 const int N = 4010; 16 const double eps = 5*1e-13; 17 const double PI = acos(-1.0); 18 19 double dcmp(double x) 20 { 21 if(fabs(x) < eps) return 0; 22 else return x < 0 ? -1 : 1; 23 } 24 25 struct Point 26 { 27 double x, y; 28 Point(double x=0, double y=0):x(x),y(y) { } 29 }; 30 31 typedef Point Vector; 32 33 Vector operator - (const Point& A, const Point& B) 34 { 35 return Vector(A.x-B.x, A.y-B.y); 36 } 37 38 double Cross(const Vector& A, const Vector& B) 39 { 40 return A.x*B.y - A.y*B.x; 41 } 42 43 double Dot(const Vector& A, const Vector& B) 44 { 45 return A.x*B.x + A.y*B.y; 46 } 47 48 bool operator < (const Point& p1, const Point& p2) 49 { 50 return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y); 51 } 52 53 bool operator == (const Point& p1, const Point& p2) 54 { 55 return p1.x == p2.x && p1.y == p2.y; 56 } 57 58 bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2) 59 { 60 double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1), 61 c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1); 62 return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0; 63 } 64 65 bool OnSegment(const Point& p, const Point& a1, const Point& a2) 66 { 67 return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0; 68 } 69 70 // 点集凸包 71 // 如果不希望在凸包的边上有输入点,把两个 <= 改成 < 72 // 如果不介意点集被修改,可以改成传递引用 73 vector<Point> ConvexHull(vector<Point> p) 74 { 75 // 预处理,删除重复点 76 sort(p.begin(), p.end()); 77 p.erase(unique(p.begin(), p.end()), p.end()); 78 79 int n = p.size(); 80 int m = 0; 81 vector<Point> ch(n+1); 82 for(int i = 0; i < n; i++) 83 { 84 while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; 85 ch[m++] = p[i]; 86 } 87 int k = m; 88 for(int i = n-2; i >= 0; i--) 89 { 90 while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; 91 ch[m++] = p[i]; 92 } 93 if(n > 1) m--; 94 ch.resize(m); 95 return ch; 96 } 97 98 int IsPointInPolygon(const Point& p, const vector<Point>& poly) 99 { 100 int wn = 0; 101 int n = poly.size(); 102 for(int i = 0; i < n; i++) 103 { 104 const Point& p1 = poly[i]; 105 const Point& p2 = poly[(i+1)%n]; 106 if(p1 == p || p2 == p || OnSegment(p, p1, p2)) return -1; // 在边界上 107 int k = dcmp(Cross(p2-p1, p-p1)); 108 int d1 = dcmp(p1.y - p.y); 109 int d2 = dcmp(p2.y - p.y); 110 if(k > 0 && d1 <= 0 && d2 > 0) wn++; 111 if(k < 0 && d2 <= 0 && d1 > 0) wn--; 112 } 113 if (wn != 0) return 1; // 内部 114 return 0; // 外部 115 } 116 117 bool ConvexPolygonDisjoint(const vector<Point> ch1, const vector<Point> ch2) 118 { 119 int c1 = ch1.size(); 120 int c2 = ch2.size(); 121 for(int i = 0; i < c1; i++) 122 if(IsPointInPolygon(ch1[i], ch2) != 0) return false; // 内部或边界上 123 for(int i = 0; i < c2; i++) 124 if(IsPointInPolygon(ch2[i], ch1) != 0) return false; // 内部或边界上 125 for(int i = 0; i < c1; i++) 126 for(int j = 0; j < c2; j++) 127 if(SegmentProperIntersection(ch1[i], ch1[(i+1)%c1], ch2[j], ch2[(j+1)%c2])) return false; 128 return true; 129 } 130 131 int main() 132 { 133 int n, m; 134 while(scanf("%d%d", &n, &m) == 2 && n > 0 && m > 0) 135 { 136 vector<Point> P1, P2; 137 double x, y; 138 for(int i = 0; i < n; i++) 139 { 140 scanf("%lf%lf", &x, &y); 141 P1.push_back(Point(x, y)); 142 } 143 for(int i = 0; i < m; i++) 144 { 145 scanf("%lf%lf", &x, &y); 146 P2.push_back(Point(x, y)); 147 } 148 if(ConvexPolygonDisjoint(ConvexHull(P1), ConvexHull(P2))) 149 printf("Yes\n"); 150 else 151 printf("No\n"); 152 } 153 return 0; 154 }
标签:
原文地址:http://www.cnblogs.com/ITUPC/p/4883853.html