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的运行机制及初步相关配置(jdk)
    观察者模式
    Shiro的 rememberMe 功能使用指导(为什么rememberMe设置了没作用?)
    MyBatis—实现关联表查询
    Mybatis解决字段名与实体类属性名不相同的冲突
    Mybatis简化sql书写,别名的使用
    十八.模块
    十七.偏函数
    十六.装饰器
    十五.匿名函数
  • 原文地址:https://www.cnblogs.com/LyonLys/p/uva_10256_Lyon.html
Copyright © 2011-2022 走看看