LA 3263 (平面图的欧拉定理) That Nice Euler Circuit

题意:

平面上有n个端点的一笔画,最后一个端点与第一个端点重合,即所给图案是闭合曲线。求这些线段将平面分成多少部分。

分析:

平面图中欧拉定理:设平面的顶点数、边数和面数分别为V、E和F。则 V+F-E=2

所求结果不容易直接求出,因此我们可以转换成 F=E-V+2

枚举两条边,如果有交点则顶点数+1,并将交点记录下来

所有交点去重(去重前记得排序),如果某个交点在线段上,则边数+1

  1 //#define LOCAL
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 using namespace std;
  7 
  8 const int maxn = 300 + 10;
  9 
 10 struct Point
 11 {
 12     double x, y;
 13     Point(double x=0, double y=0) :x(x),y(y) {}
 14 };
 15 typedef Point Vector;
 16 const double EPS = 1e-10;
 17 
 18 Vector operator + (Vector A, Vector B)    { return Vector(A.x + B.x, A.y + B.y); }
 19 
 20 Vector operator - (Vector A, Vector B)    { return Vector(A.x - B.x, A.y - B.y); }
 21 
 22 Vector operator * (Vector A, double p)    { return Vector(A.x*p, A.y*p); }
 23 
 24 Vector operator / (Vector A, double p)    { return Vector(A.x/p, A.y/p); }
 25 
 26 bool operator < (const Point& a, const Point& b)
 27 { return a.x < b.x || (a.x == b.x && a.y < b.y); }
 28 
 29 int dcmp(double x)
 30 { if(fabs(x) < EPS) return 0;
 31  else return x < 0 ? -1 : 1; }
 32 
 33 bool operator == (const Point& a, const Point& b)
 34 { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; }
 35 
 36 double Dot(Vector A, Vector B)
 37 { return A.x*B.x + A.y*B.y; }
 38 
 39 double Length(Vector A)    { return sqrt(Dot(A, A)); }
 40 
 41 double Angle(Vector A, Vector B)
 42 { return acos(Dot(A, B) / Length(A) / Length(B)); }
 43 
 44 double Cross(Vector A, Vector B)
 45 { return A.x*B.y - A.y*B.x; }
 46 
 47 double Area2(Point A, Point B, Point C)
 48 { return Cross(B-A, C-A); }
 49 
 50 Vector VRotate(Vector A, double rad)
 51 {
 52     return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
 53 }
 54 
 55 Point PRotate(Point A, Point B, double rad)
 56 {
 57     return A + VRotate(B-A, rad);
 58 }
 59 
 60 Vector Normal(Vector A)
 61 {
 62     double l = Length(A);
 63     return Vector(-A.y/l, A.x/l);
 64 }
 65 
 66 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)
 67 {
 68     Vector u = P - Q;
 69     double t = Cross(w, u) / Cross(v, w);
 70     return P + v*t;
 71 }
 72 double DistanceToLine(Point P, Point A, Point B)
 73 {
 74     Vector v1 = B - A, v2 = P - A;
 75     return fabs(Cross(v1, v2)) / Length(v1);
 76 }
 77 
 78 double DistanceToSegment(Point P, Point A, Point B)
 79 {
 80     if(A == B)    return Length(P - A);
 81     Vector v1 = B - A, v2 = P - A, v3 = P - B;
 82     if(dcmp(Dot(v1, v2)) < 0)    return Length(v2);
 83     else if(dcmp(Dot(v1, v3)) > 0)    return Length(v3);
 84     else return fabs(Cross(v1, v2)) / Length(v1);
 85 }
 86 
 87 Point GetLineProjection(Point P, Point A, Point B)
 88 {
 89     Vector v = B - A;
 90     return A + v * (Dot(v, P - A) / Dot(v, v));
 91 }
 92 
 93 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
 94 {
 95     double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1);
 96     double c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);
 97     return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
 98 }
 99 
100 bool OnSegment(Point P, Point a1, Point a2)
101 {
102     Vector v1 = a1 - P, v2 = a2 - P;
103     return dcmp(Cross(v1, v2)) == 0 && dcmp(Dot(v1, v2)) < 0;
104 }
105 
106 Point P[maxn], V[maxn*maxn];
107 
108 int main(void)
109 {
110     #ifdef    LOCAL
111         freopen("3263in.txt", "r", stdin);
112     #endif
113 
114     int n, kase = 0;
115     while(scanf("%d", &n) == 1 && n)
116     {
117         for(int i = 0; i < n; ++i)
118         {
119             scanf("%lf%lf", &P[i].x, &P[i].y);
120             V[i] = P[i];
121         }
122         n--;
123         int c = n, e = n;
124 
125         for(int i = 0; i < n; ++i)
126             for(int j = i+1; j < n; ++j)
127                 if(SegmentProperIntersection(P[i], P[i+1], P[j], P[j+1]))
128                     V[c++] = GetLineIntersection(P[i], P[i+1]-P[i], P[j], P[j+1]-P[j]);
129 
130         sort(V, V+c);
131         c = unique(V, V+c) - V;
132 
133         for(int i = 0; i < c; ++i)
134             for(int j = 0; j < n; ++j)
135                 if(OnSegment(V[i], P[j], P[j+1]))    e++;
136 
137         printf("Case %d: There are %d pieces.
", ++kase, e+2-c);
138     }
139 
140     return 0;
141 }
代码君
原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4022863.html