zoukankan      html  css  js  c++  java
  • uva 10256 The Great Divide (Convex Hull, Simple)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=14&page=show_problem&problem=1197

      题意是给出两堆点,问是否能找到一条直线将这两堆点分开,有就输出“Yes”,否则输出“No”。

      构建两个凸包,如果存在这样的一条直线,那么这两个凸包必然不相交。构建完凸包以后,就是枚举每条边,判断两个凸包是否有相交的部分。

    代码如下:

    View Code
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <set>
      5 #include <vector>
      6 #include <iostream>
      7 #include <algorithm>
      8 
      9 using namespace std;
     10 
     11 struct Point {
     12     double x, y;
     13     Point() {}
     14     Point(double x, double y) : x(x), y(y) {}
     15 } ;
     16 template<class T> T sqr(T x) { return x * x;}
     17 inline double ptDis(Point a, Point b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
     18 
     19 // basic calculations
     20 typedef Point Vec;
     21 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
     22 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
     23 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
     24 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
     25 
     26 const double EPS = 5e-13;
     27 const double PI = acos(-1.0);
     28 inline int sgn(double x) { return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}
     29 bool operator < (Point a, Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y);}
     30 bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;}
     31 
     32 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
     33 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
     34 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
     35 inline double vecLen(Vec x) { return sqrt(sqr(x.x) + sqr(x.y));}
     36 inline double toRad(double deg) { return deg / 180.0 * PI;}
     37 inline double angle(Vec v) { return atan2(v.y, v.x);}
     38 inline double angle(Vec a, Vec b) { return acos(dotDet(a, b) / vecLen(a) / vecLen(b));}
     39 inline double triArea(Point a, Point b, Point c) { return fabs(crossDet(b - a, c - a));}
     40 inline Vec vecUnit(Vec x) { return x / vecLen(x);}
     41 inline Vec rotate(Vec x, double rad) { return Vec(x.x * cos(rad) - x.y * sin(rad), x.x * sin(rad) + x.y * cos(rad));}
     42 Vec normal(Vec x) {
     43     double len = vecLen(x);
     44     return Vec(- x.y / len, x.x / len);
     45 }
     46 
     47 struct Line {
     48     Point s, t;
     49     Line() {}
     50     Line(Point s, Point t) : s(s), t(t) {}
     51     Point point(double x) {
     52         return s + (t - s) * x;
     53     }
     54     Line move(double x) {
     55         Vec nor = normal(t - s);
     56         nor = nor / vecLen(nor) * x;
     57         return Line(s + nor, t + nor);
     58     }
     59     Vec vec() { return t - s;}
     60 } ;
     61 typedef Line Seg;
     62 
     63 inline bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0;}
     64 inline bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);}
     65 
     66 // 0 : not intersect
     67 // 1 : proper intersect
     68 // 2 : improper intersect
     69 int segIntersect(Point a, Point c, Point b, Point d) {
     70     Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
     71     int a_bc = sgn(crossDet(v1, v2));
     72     int b_cd = sgn(crossDet(v2, v3));
     73     int c_da = sgn(crossDet(v3, v4));
     74     int d_ab = sgn(crossDet(v4, v1));
     75     if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1;
     76     if (onSeg(b, a, c) && c_da) return 2;
     77     if (onSeg(c, b, d) && d_ab) return 2;
     78     if (onSeg(d, c, a) && a_bc) return 2;
     79     if (onSeg(a, d, b) && b_cd) return 2;
     80     return 0;
     81 }
     82 inline int segIntersect(Seg a, Seg b) { return segIntersect(a.s, a.t, b.s, b.t);}
     83 
     84 // point of the intersection of 2 lines
     85 Point lineIntersect(Point P, Vec v, Point Q, Vec w) {
     86     Vec u = P - Q;
     87     double t = crossDet(w, u) / crossDet(v, w);
     88     return P + v * t;
     89 }
     90 inline Point lineIntersect(Line a, Line b) { return lineIntersect(a.s, a.t - a.s, b.s, b.t - b.s);}
     91 
     92 // Warning: This is a DIRECTED Distance!!!
     93 double pt2Line(Point x, Point a, Point b) {
     94     Vec v1 = b - a, v2 = x - a;
     95     return crossDet(v1, v2) / vecLen(v1);
     96 }
     97 inline double pt2Line(Point x, Line L) { return pt2Line(x, L.s, L.t);}
     98 
     99 double pt2Seg(Point x, Point a, Point b) {
    100     if (a == b) return vecLen(x - a);
    101     Vec v1 = b - a, v2 = x - a, v3 = x - b;
    102     if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
    103     if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
    104     return fabs(crossDet(v1, v2)) / vecLen(v1);
    105 }
    106 inline double pt2Seg(Point x, Seg s) { return pt2Seg(x, s.s, s.t);}
    107 
    108 struct Poly {
    109     vector<Point> pt;
    110     Poly() { pt.clear();}
    111     Poly(vector<Point> pt) : pt(pt) {}
    112     Point operator [] (int x) const { return pt[x];}
    113     int size() { return pt.size();}
    114     double area() {
    115         double ret = 0.0;
    116         int sz = pt.size();
    117         for (int i = 1; i < sz; i++) {
    118             ret += crossDet(pt[i], pt[i - 1]);
    119         }
    120         return fabs(ret / 2.0);
    121     }
    122 } ;
    123 
    124 struct Circle {
    125     Point c;
    126     double r;
    127     Circle() {}
    128     Circle(Point c, double r) : c(c), r(r) {}
    129     Point point(double a) {
    130         return Point(c.x + cos(a) * r, c.y + sin(a) * r);
    131     }
    132 } ;
    133 
    134 int lineCircleIntersect(Line L, Circle C, double &t1, double &t2, vector<Point> &sol) {
    135     double a = L.s.x, b = L.t.x - C.c.x, c = L.s.y, d = L.t.y - C.c.y;
    136     double e = sqr(a) + sqr(c), f = 2 * (a * b + c * d), g = sqr(b) + sqr(d) - sqr(C.r);
    137     double delta = sqr(f) - 4.0 * e * g;
    138     if (sgn(delta) < 0) return 0;
    139     if (sgn(delta) == 0) {
    140         t1 = t2 = -f / (2.0 * e);
    141         sol.push_back(L.point(t1));
    142         return 1;
    143     }
    144     t1 = (-f - sqrt(delta)) / (2.0 * e);
    145     sol.push_back(L.point(t1));
    146     t2 = (-f + sqrt(delta)) / (2.0 * e);
    147     sol.push_back(L.point(t2));
    148     return 2;
    149 }
    150 
    151 int lineCircleIntersect(Line L, Circle C, vector<Point> &sol) {
    152     Vec dir = L.t - L.s, nor = normal(dir);
    153     Point mid = lineIntersect(C.c, nor, L.s, dir);
    154     double len = sqr(C.r) - sqr(ptDis(C.c, mid));
    155     if (sgn(len) < 0) return 0;
    156     if (sgn(len) == 0) {
    157         sol.push_back(mid);
    158         return 1;
    159     }
    160     Vec dis = vecUnit(dir);
    161     len = sqrt(len);
    162     sol.push_back(mid + dis * len);
    163     sol.push_back(mid - dis * len);
    164     return 2;
    165 }
    166 
    167 // -1 : coincide
    168 int circleCircleIntersect(Circle C1, Circle C2, vector<Point> &sol) {
    169     double d = vecLen(C1.c - C2.c);
    170     if (sgn(d) == 0) {
    171         if (sgn(C1.r - C2.r) == 0) {
    172             return -1;
    173         }
    174         return 0;
    175     }
    176     if (sgn(C1.r + C2.r - d) < 0) return 0;
    177     if (sgn(fabs(C1.r - C2.r) - d) > 0) return 0;
    178     double a = angle(C2.c - C1.c);
    179     double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2.0 * C1.r * d));
    180     Point p1 = C1.point(a - da), p2 = C1.point(a + da);
    181     sol.push_back(p1);
    182     if (p1 == p2) return 1;
    183     sol.push_back(p2);
    184     return 2;
    185 }
    186 
    187 void circleCircleIntersect(Circle C1, Circle C2, vector<double> &sol) {
    188     double d = vecLen(C1.c - C2.c);
    189     if (sgn(d) == 0) return ;
    190     if (sgn(C1.r + C2.r - d) < 0) return ;
    191     if (sgn(fabs(C1.r - C2.r) - d) > 0) return ;
    192     double a = angle(C2.c - C1.c);
    193     double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2.0 * C1.r * d));
    194     sol.push_back(a - da);
    195     sol.push_back(a + da);
    196 }
    197 
    198 int tangent(Point p, Circle C, vector<Vec> &sol) {
    199     Vec u = C.c - p;
    200     double dist = vecLen(u);
    201     if (dist < C.r) return 0;
    202     if (sgn(dist - C.r) == 0) {
    203         sol.push_back(rotate(u, PI / 2.0));
    204         return 1;
    205     }
    206     double ang = asin(C.r / dist);
    207     sol.push_back(rotate(u, -ang));
    208     sol.push_back(rotate(u, ang));
    209     return 2;
    210 }
    211 
    212 // ptA : points of tangency on circle A
    213 // ptB : points of tangency on circle B
    214 int tangent(Circle A, Circle B, vector<Point> &ptA, vector<Point> &ptB) {
    215     if (A.r < B.r) {
    216         swap(A, B);
    217         swap(ptA, ptB);
    218     }
    219     int d2 = sqr(A.c.x - B.c.x) + sqr(A.c.y - B.c.y);
    220     int rdiff = A.r - B.r, rsum = A.r + B.r;
    221     if (d2 < sqr(rdiff)) return 0;
    222     double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
    223     if (d2 == 0 && A.r == B.r) return -1;
    224     if (d2 == sqr(rdiff)) {
    225         ptA.push_back(A.point(base));
    226         ptB.push_back(B.point(base));
    227         return 1;
    228     }
    229     double ang = acos((A.r - B.r) / sqrt(d2));
    230     ptA.push_back(A.point(base + ang));
    231     ptB.push_back(B.point(base + ang));
    232     ptA.push_back(A.point(base - ang));
    233     ptB.push_back(B.point(base - ang));
    234     if (d2 == sqr(rsum)) {
    235         ptA.push_back(A.point(base));
    236         ptB.push_back(B.point(PI + base));
    237     } else if (d2 > sqr(rsum)) {
    238         ang = acos((A.r + B.r) / sqrt(d2));
    239         ptA.push_back(A.point(base + ang));
    240         ptB.push_back(B.point(PI + base + ang));
    241         ptA.push_back(A.point(base - ang));
    242         ptB.push_back(B.point(PI + base - ang));
    243     }
    244     return (int) ptA.size();
    245 }
    246 
    247 void getCoor(double R, double lat, double lng, double &x, double &y, double &z) {
    248     lat = toRad(lat);
    249     lng = toRad(lng);
    250     x = R * cos(lat) * cos(lng);
    251     y = R * cos(lat) * sin(lng);
    252     z = R * sin(lat);
    253 }
    254 
    255 // -1 : onside
    256 // 0 : outside
    257 // 1 : inside
    258 int ptInPoly(Point p, Poly poly) {
    259     int wn = 0, sz = poly.size();
    260     for (int i = 0; i < sz; i++) {
    261         if (onSeg(p, poly[i], poly[(i + 1) % sz])) return -1;
    262         int k = sgn(crossDet(poly[(i + 1) % sz] - poly[i], p - poly[i]));
    263         int d1 = sgn(poly[i].y - p.y);
    264         int d2 = sgn(poly[(i + 1) % sz].y - p.y);
    265         if (k > 0 && d1 <= 0 && d2 > 0) wn++;
    266         if (k < 0 && d2 <= 0 && d1 > 0) wn--;
    267     }
    268     if (wn != 0) return 1;
    269     return 0;
    270 }
    271 
    272 // if DO NOT need a high precision
    273 /*
    274 int ptInPoly(Point p, Poly poly) {
    275     int sz = poly.size();
    276     double ang = 0.0, tmp;
    277     for (int i = 0; i < sz; i++) {
    278         if (onSeg(p, poly[i], poly[(i + 1) % sz])) return -1;
    279         tmp = angle(poly[i] - p) - angle(poly[(i + 1) % sz] - p) + PI;
    280         ang += tmp - floor(tmp / (2.0 * PI)) * 2.0 * PI - PI;
    281     }
    282     if (sgn(ang - PI) == 0) return -1;
    283     if (sgn(ang) == 0) return 0;
    284     return 1;
    285 }
    286 */
    287 
    288 // convex hull algorithms
    289 
    290 // andwer's algorithm
    291 // if DO NOT want the points on the side of convex hull, change all "<" into "<="
    292 // return the number of points in convex hull
    293 int andrew(Point *pt, int n, Point *ch) {
    294     sort(pt, pt + n);
    295     int m = 0;
    296     for (int i = 0; i < n; i++) {
    297         while (m > 1 && crossDet(ch[m - 1] - ch[m - 2], pt[i] - ch[m - 2]) < 0) m--;
    298         ch[m++] = pt[i];
    299     }
    300     int k = m;
    301     for (int i = n - 2; i >= 0; i--) {
    302         while (m > k && crossDet(ch[m - 1] - ch[m - 2], pt[i] - ch[m - 2]) < 0) m--;
    303         ch[m++] = pt[i];
    304     }
    305     if (n > 1) m--;
    306     return m;
    307 }
    308 
    309 // graham's algorithm
    310 // if DO NOT want the points on the side of convex hull, change all "<=" into "<"
    311 Point origin;
    312 inline bool cmpAng(Point p1, Point p2) { return crossDet(origin, p1, p2) > 0;}
    313 inline bool cmpDis(Point p1, Point p2) { return ptDis(p1, origin) > ptDis(p2, origin);}
    314 
    315 void removePt(Point *pt, int &n) {
    316     int idx = 1;
    317     for (int i = 2; i < n; i++) {
    318         if (sgn(crossDet(origin, pt[i], pt[idx]))) pt[++idx] = pt[i];
    319         else if (cmpDis(pt[i], pt[idx])) pt[idx] = pt[i];
    320     }
    321     n = idx + 1;
    322 }
    323 
    324 int graham(Point *pt, int n, Point *ch) {
    325     int top = -1;
    326     for (int i = 1; i < n; i++) {
    327         if (pt[i].y < pt[0].y || (pt[i].y == pt[0].y && pt[i].x < pt[0].x)) swap(pt[i], pt[0]);
    328     }
    329     origin = pt[0];
    330     sort(pt + 1, pt + n, cmpAng);
    331     removePt(pt, n);
    332     for (int i = 0; i < n; i++) {
    333         if (i >= 2) {
    334             while (!(crossDet(ch[top - 1], pt[i], ch[top]) <= 0)) top--;
    335         }
    336         ch[++top] = pt[i];
    337     }
    338     return top + 1;
    339 }
    340 
    341 /****************** template above *******************/
    342 
    343 #define REP(i, n) for (int i = 0; i < (n); i++)
    344 #define REP_1(i, n) for (int i = 1; i <= (n); i++)
    345 
    346 const int N = 555;
    347 Point setA[N], setB[N], conA[N], conB[N];
    348 Poly PA, PB;
    349 
    350 bool work(int n, int m) {
    351     REP(i, n) {
    352         if (ptInPoly(setA[i], PB)) return false;
    353     }
    354     REP(i, m) {
    355         if (ptInPoly(setB[i], PA)) return false;
    356     }
    357     REP(i, n) {
    358         REP(j, m) {
    359             if (segIntersect(conA[i], conA[i + 1], conB[j], conB[j + 1])) return false;
    360         }
    361     }
    362     return true;
    363 }
    364 
    365 int main() {
    366 //    freopen("in", "r", stdin);
    367     int n, m;
    368     while (cin >> n >> m && (n || m)) {
    369         REP(i, n) cin >> setA[i].x >> setA[i].y;
    370         REP(i, m) cin >> setB[i].x >> setB[i].y;
    371         n = andrew(setA, n, conA);
    372         m = andrew(setB, m, conB);
    373         conA[n] = conA[0];
    374         conB[m] = conB[0];
    375         PA = Poly(), PB = Poly();
    376         REP(i, n) {
    377             PA.pt.push_back(setA[i]);
    378         }
    379         REP(i, m) {
    380             PB.pt.push_back(setB[i]);
    381         }
    382         if (work(n, m)) puts("Yes");
    383         else puts("No");
    384     }
    385     return 0;
    386 }

    ——written by Lyon

  • 相关阅读:
    Java实现 蓝桥杯 算法提高 特等奖学金(暴力)
    Java实现 蓝桥杯 算法提高 特等奖学金(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    第一届云原生应用大赛火热报名中! helm install “一键安装”应用触手可及!
    云原生时代,2个方案轻松加速百万级镜像
    Knative 基本功能深入剖析:Knative Serving 自动扩缩容 Autoscaler
  • 原文地址:https://www.cnblogs.com/LyonLys/p/uva_10256_Lyon.html
Copyright © 2011-2022 走看看