LA 3263 That Nice Euler Circuit (2D Geometry)

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1264

  看刘汝佳的训练指南过的第一道计算几何题。开始的时候看到这题就觉得这是水题,于是瞬间就把代码打出来了。不过在debug的时候,搞着搞着发现如果像我一开始的时候那样做,好多特殊情况不能正常处理,加了好多特判都还是能找出bug。最后在搞出下面那么多数据,觉得这样特判简直就是一个无底洞,根本就不能正确的得到答案。。。- - 最后在wa到忍不住的情况下,只好求助于佳哥的题解了。。

  看了一下他的代码,瞬间觉得豁然开朗,原来之前那么的多的特判都可以通过这样的方法来消除。

  简单说一下他的做法。首先,我们可以知道顶点数V+边数E-面数F=2这个基本定理。然后,这个图形的顶点数是可以在两两判相交的时候得到的,我用一个set来保存这些个数。边数是解这题的一个关键,边数至少有n-1条,这是显而易见的,然而某些边是被分割成多少段呢?这时候就需要将我们找到的点放进线段,看看有没有将一条线段分割,有的话就将总的边数加一。因为将点放进set里了,所以所有点都是唯一的。也就是不会有同一个位置的点对同一条线段分割多于一次。最后套进欧拉定理,就可以正确的把这题解决了。

代码如下:

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 #define REP(i, n) for (int i = 0; i < (n); i++)
 12 
 13 struct Point {
 14     double x, y;
 15     Point() {}
 16     Point(double x, double y) : x(x), y(y) {}
 17 } ;
 18 template<class T> T sqr(T x) { return x * x;}
 19 
 20 // basic calculations
 21 typedef Point Vec;
 22 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
 23 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
 24 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
 25 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
 26 
 27 const double eps = 1e-8;
 28 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 double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
 33 double vecLen(Vec x) { return sqrt(sqr(x.x) + sqr(x.y));}
 34 double angle(Vec a, Vec b) { return acos(dotDet(a, b) / vecLen(a) / vecLen(b));}
 35 double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
 36 double triArea(Point a, Point b, Point c) { return fabs(crossDet(b - a, c - a));}
 37 Vec rotate(Vec x, double rad) { return Vec(x.x * cos(rad) - x.y * sin(rad), x.x * sin(rad) + x.y * cos(rad));}
 38 Vec normal(Vec x) {
 39     double len = vecLen(x);
 40     return Vec(- x.y / len, x.x / len);
 41 }
 42 
 43 struct Line {
 44     Point s, t;
 45     Line() {}
 46     Line(Point s, Point t) : s(s), t(t) {}
 47 } ;
 48 typedef Line Seg;
 49 
 50 bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0;}
 51 bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);}
 52 // 0 : not intersect
 53 // 1 : proper intersect
 54 // 2 : improper intersect
 55 int segIntersect(Point a, Point c, Point b, Point d) {
 56     Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
 57     int a_bc = sgn(crossDet(v1, v2));
 58     int b_cd = sgn(crossDet(v2, v3));
 59     int c_da = sgn(crossDet(v3, v4));
 60     int d_ab = sgn(crossDet(v4, v1));
 61     if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1;
 62     if (onSeg(b, a, c) && c_da) return 2;
 63     if (onSeg(c, b, d) && d_ab) return 2;
 64     if (onSeg(d, c, a) && a_bc) return 2;
 65     if (onSeg(a, d, b) && b_cd) return 2;
 66     return 0;
 67 }
 68 int segIntersect(Seg a, Seg b) { return segIntersect(a.s, a.t, b.s, b.t);}
 69 
 70 // point of the intersection of 2 lines
 71 Point lineIntersect(Point P, Vec v, Point Q, Vec w) {
 72     Vec u = P - Q;
 73     double t = crossDet(w, u) / crossDet(v, w);
 74     return P + v * t;
 75 }
 76 Point lineIntersect(Line a, Line b) { return lineIntersect(a.s, a.t - a.s, b.s, b.t - b.s);}
 77 
 78 // directed distance
 79 double pt2Line(Point x, Point a, Point b) {
 80     Vec v1 = b - a, v2 = x - a;
 81     return crossDet(v1, v2) / vecLen(v1);
 82 }
 83 double pt2Line(Point x, Line L) { return pt2Line(x, L.s, L.t);}
 84 
 85 double pt2Seg(Point x, Point a, Point b) {
 86     if (a == b) return vecLen(x - a);
 87     Vec v1 = b - a, v2 = x - a, v3 = x - b;
 88     if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
 89     if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
 90     return fabs(crossDet(v1, v2)) / vecLen(v1);
 91 }
 92 double pt2Seg(Point x, Seg s) { return pt2Seg(x, s.s, s.t);}
 93 
 94 struct Poly {
 95     vector<Point> pt;
 96     Poly() {}
 97     Poly(vector<Point> pt) : pt(pt) {}
 98     double area() {
 99         double ret = 0.0;
100         int sz = pt.size();
101         for (int i = 1; i < sz; i++) {
102             ret += crossDet(pt[i], pt[i - 1]);
103         }
104         return fabs(ret / 2.0);
105     }
106 } ;
107 
108 /****************** template above *******************/
109 
110 Poly poly;
111 
112 int main() {
113 //    freopen("in", "r", stdin);
114     int cas = 1, n;
115     while (cin >> n && n) {
116         set<Point> pt;
117         pt.clear();
118         poly.pt.clear();
119         int ln = n - 1;
120         double x, y;
121         for (int i = 0; i < n; i++) {
122             cin >> x >> y;
123             poly.pt.push_back(Point(x, y));
124             pt.insert(Point(x, y));
125             for (int j = 1; j < i; j++) {
126                 int st = segIntersect(Line(poly.pt[i - 1], poly.pt[i]), Line(poly.pt[j - 1], poly.pt[j]));
127                 if (st == 1) {
128                     pt.insert(lineIntersect(Line(poly.pt[i - 1], poly.pt[i]), Line(poly.pt[j - 1], poly.pt[j])));
129                 }
130             }
131         }
132         for (set<Point>::iterator si = pt.begin(); si != pt.end(); si++) {
133             for (int i = 1; i < n; i++) {
134                 if (onSeg(*si, poly.pt[i - 1], poly.pt[i])) ln++;
135             }
136         }
137         cout << "Case " << cas++ << ": There are " << ln - pt.size() + 2 << " pieces." << endl;
138     }
139     return 0;
140 }

数据如下:

View Code
  1 5
  2 0 0
  3 0 1
  4 1 1
  5 1 0
  6 0 0
  7 
  8 7
  9 1 1
 10 1 5
 11 2 1
 12 2 5
 13 5 1
 14 3 5
 15 1 1
 16 
 17 11
 18 0 0
 19 4 0
 20 8 0
 21 8 1
 22 7 0
 23 6 1
 24 4 0
 25 3 1
 26 2 0
 27 0 1
 28 0 0
 29 
 30 7
 31 0 0
 32 1 0
 33 2 0
 34 2 1
 35 1 0
 36 0 1
 37 0 0
 38 
 39 12
 40 0 0
 41 1 -1
 42 2 0
 43 1 1
 44 0 0
 45 2 0
 46 2 1
 47 0 1
 48 0 0
 49 -1 -1
 50 0 -1
 51 0 0
 52 
 53 11
 54 0 0
 55 4 0
 56 8 0
 57 8 1
 58 7 0
 59 6 1
 60 4 0
 61 3 1
 62 2 0
 63 0 1
 64 0 0
 65 
 66 5
 67 0 0
 68 10 0
 69 5 5
 70 5 -5
 71 0 0
 72 
 73 7
 74 0 0
 75 0 -1
 76 1 0
 77 -1 0
 78 1 -2
 79 1 1
 80 0 0
 81 
 82 11
 83 0 0
 84 1 0
 85 1 1
 86 -1 -1
 87 0 -1
 88 0 1
 89 -1 1
 90 1 -1
 91 0 -2
 92 -2 0
 93 0 0
 94 
 95 14
 96 0 0
 97 1 0
 98 1 1
 99 -1 -1
100 0 -1
101 0 1
102 -1 1
103 1 -1
104 0 -2
105 -2 0
106 0 0
107 100 101
108 99 101
109 0 0
110 
111 16
112 0 0
113 1 0
114 1 1
115 -1 -1
116 0 -1
117 0 1
118 -1 1
119 1 -1
120 0 -2
121 -2 0
122 0 0
123 100 101
124 99 101
125 -99 -101
126 -100 -101
127 0 0
128 
129 0

——written by Lyon

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