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.\n", ++kase, e+2-c);
138     }
139
140     return 0;
141 }

代码君

时间: 2024-10-19 01:03:33

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

平面上欧拉定理:poj 2284( LA 3263 ) That Nice Euler Circuit

3263 - That Nice Euler Circuit Time limit: 3.000 seconds Description Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his primary school Joey heard about the nice story of how Euler started the study abo

LA 3236 That Nice Euler Circuit(欧拉定理)

That Nice Euler Circuit Timelimit:3.000 seconds Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his primary school Joey heard about the nice story of how Euler started the study about graphs. The proble

UVALive 3263 That Nice Euler Circuit 计算几何欧拉定理

欧拉定理:P+F-E=2 That Nice Euler Circuit Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his primary schoo

UVALive - 3263 That Nice Euler Circuit (几何)

UVALive - 3263 That Nice Euler Circuit (几何) ACM 题目地址: UVALive - 3263 That Nice Euler Circuit 题意: 给出一个点,问连起来后的图形把平面分为几个区域. 分析: 欧拉定理有:设平面图的顶点数.边数.面数分别V,E,F则V+F-E=2 大白的题目,做起来还是很有技巧的. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: LA3263.cpp * C

UVALive - 3263 - That Nice Euler Circuit (计算几何~~)

UVALive - 3263 That Nice Euler Circuit Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his primary sch

zoj2589Circles(平面图的欧拉定理)

链接 连通图中: 设一个平面图形的顶点数为n,划分区域数为r,一笔画笔数为也就是边数m,则有: n+r-m=2 那么不算外面的那个大区域的话 就可以写为 n+r-m = 1 那么这个题就可以依次求出每个连通图的r = m-n+1 累加起来 最后加上最外面那个平面. 注意交点的去重,对于一个圆的边数其实就是交点的数量(排除没有交点的情况) 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #inc

【UVA】1342 - That Nice Euler Circuit(几何+欧拉定理)

E 为边数 ,V 为点数,F为面数 那么 F = E + 2 - V(其中包括了一个无限大的面) 这道题被自己的习惯坑了一下#define MAXD 300 + 10 和#define MAXD 310 是不一样的 14113235 1342 That Nice Euler Circuit Accepted C++ 0.082 2014-08-29 15:12:20 自己的代码: #include<cstdio> #include<cstring> #include<iost

poj2284 That Nice Euler Circuit(欧拉公式)

题目链接:poj2284 That Nice Euler Circuit 欧拉公式:如果G是一个阶为n,边数为m且含有r个区域的连通平面图,则有恒等式:n-m+r=2. 欧拉公式的推广: 对于具有k(k≥2)个连通分支的平面图G,有:n-m+r=k+1. 题意:给出连通平面图的各顶点,求这个欧拉回路将平面分成多少区域. 题解:根据平面图的欧拉定理“n-m+r=2”来求解区域数r. 顶点个数n:两两线段求交点,每个交点都是图中的顶点. 边数m:在求交点时判断每个交点落在第几条边上,如果一个交点落在

POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)

That Nice Euler Circuit Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 1977   Accepted: 626 Description Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his primary school Joey heard about