uva 11665 Chinese Ink (几何+并查集)

UVA 11665

  随便给12的找了一道我没做过的几何基础题。这题挺简单的,不过uva上通过率挺低,通过人数也不多。

  题意是要求给出的若干多边形组成多少个联通块。做的时候要注意这题是不能用double浮点类型的,然后判多边形交只需要两个条件,存在边规范相交,或者存在一个多边形上的顶点在另一个多边形上或者在多边形内。

代码如下:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 const double EPS = 1e-10;
  9 const int N = 44;
 10 const int M = 11;
 11 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
 12 
 13 struct Point {
 14     int x, y;
 15     Point() {}
 16     Point(int x, int y) : x(x), y(y) {}
 17     Point operator + (Point a) { return Point(x + a.x, y + a.y);}
 18     Point operator - (Point a) { return Point(x - a.x, y - a.y);}
 19     Point operator * (int p) { return Point(x * p, y * p);}
 20     Point operator / (int p) { return Point(x / p, y / p);}
 21 } ;
 22 
 23 inline int cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
 24 inline int dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
 25 
 26 inline bool onseg(Point x, Point a, Point b) { return sgn(cross(a - x, b - x)) == 0 && sgn(dot(a - x, b - x)) <= 0;}
 27 bool ptinpoly(Point x, Point *pt, int n) {
 28     pt[n] = pt[0];
 29     int wn = 0;
 30     for (int i = 0; i < n; i++) {
 31         if (onseg(x, pt[i], pt[i + 1])) return true;
 32         int dr = sgn(cross(pt[i + 1] - pt[i], x - pt[i]));
 33         int k1 = sgn(pt[i + 1].y - x.y);
 34         int k2 = sgn(pt[i].y - x.y);
 35         if (dr > 0 && k1 > 0 && k2 <= 0) wn++;
 36         if (dr < 0 && k2 > 0 && k1 <= 0) wn--;
 37     }
 38     return wn != 0;
 39 }
 40 
 41 struct MFS {
 42     int fa[N], cnt;
 43     void init() { for (int i = 0; i < N; i++) fa[i] = i; cnt = 0;}
 44     int find(int x) { return fa[x] = fa[x] == x ? x : find(fa[x]);}
 45     void merge(int x, int y) {
 46         int fx = find(x);
 47         int fy = find(y);
 48         if (fx == fy) return ;
 49         cnt++;
 50         fa[fx] = fy;
 51     }
 52 } mfs;
 53 
 54 Point poly[N][M];
 55 char buf[111];
 56 int sz[N];
 57 
 58 bool ssint(Point a, Point b, Point c, Point d) {
 59     int s1 = sgn(cross(a - c, b - c));
 60     int s2 = sgn(cross(a - d, b - d));
 61     int t1 = sgn(cross(c - a, d - a));
 62     int t2 = sgn(cross(c - b, d - b));
 63     return s1 * s2 < 0 && t1 * t2 < 0;
 64 }
 65 
 66 bool polyint(int a, int b) {
 67     poly[a][sz[a]] = poly[a][0];
 68     poly[b][sz[b]] = poly[b][0];
 69     for (int i = 0; i < sz[a]; i++) {
 70         for (int j = 0; j < sz[b]; j++) {
 71             if (ssint(poly[a][i], poly[a][i + 1], poly[b][j], poly[b][j + 1])) return true;
 72         }
 73     }
 74     return false;
 75 }
 76 
 77 bool test(int a, int b) {
 78     for (int i = 0; i < sz[a]; i++) if (ptinpoly(poly[a][i], poly[b], sz[b])) return true;
 79     for (int i = 0; i < sz[b]; i++) if (ptinpoly(poly[b][i], poly[a], sz[a])) return true;
 80     if (polyint(a, b)) return true;
 81     return false;
 82 }
 83 
 84 int main() {
 85     //freopen("in", "r", stdin);
 86     int n;
 87     while (cin >> n && n) {
 88         gets(buf);
 89         char *p;
 90         mfs.init();
 91         for (int i = 0; i < n; i++) {
 92             gets(buf);
 93             p = strtok(buf, " ");
 94             for (sz[i] = 0; p; sz[i]++) {
 95                 sscanf(p, "%d", &poly[i][sz[i]].x);
 96                 p = strtok(NULL, " ");
 97                 sscanf(p, "%d", &poly[i][sz[i]].y);
 98                 p = strtok(NULL, " ");
 99             }
100             //cout << sz[i] << endl;
101             for (int j = 0; j < i; j++) if (test(i, j)) {
102                 mfs.merge(i, j);
103                 //cout << i << ' ' << j << endl;
104             }
105         }
106         cout << n - mfs.cnt << endl;
107     }
108     return 0;
109 }
View Code

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/uva_11665_Lyon.html