码迷,mamicode.com
首页 > 其他好文 > 详细

uvalive 3263 That Nice Euler Circuit

时间:2015-10-11 00:21:41      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

题意:平面上有一个包含n个端点的一笔画,第n个端点总是和第一个端点重合,因此团史一条闭合曲线。组成一笔画的线段可以相交,但是不会部分重叠。求这些线段将平面分成多少部分(包括封闭区域和无限大区域)。

分析:若是直接找出所有区域,或非常麻烦,而且容易出错。但用欧拉定理可以将问题进行转化,使解法变容易。

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

这样,只需求出顶点数V和边数E,就可以求出F=E+2-V。

设平面图的结点由两部分组成,即原来的结点和新增的结点。由于可能出现三线共点,需要删除重复的点。

技术分享
  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<memory.h>
  7 #include<cstdlib>
  8 #include<vector>
  9 #define clc(a,b) memset(a,b,sizeof(a))
 10 #define LL long long int
 11 using namespace std;
 12 const int inf=0x3f3f3f3f;
 13 const double eps = 1e-10;
 14 const int N = 300 + 5;
 15 
 16 struct Point
 17 {
 18     double x, y;
 19     Point(double x = 0, double y = 0) : x(x), y(y) { }
 20 };
 21 
 22 typedef Point Vector;
 23 
 24 Vector operator + (Vector A, Vector B)
 25 {
 26     return Vector(A.x + B.x, A.y + B.y);
 27 }
 28 
 29 Vector operator - (Point A, Point B)
 30 {
 31     return Vector(A.x - B.x, A.y - B.y);
 32 }
 33 
 34 Vector operator * (Vector A, double p)
 35 {
 36     return Vector(A.x * p, A.y * p);
 37 }
 38 
 39 Vector operator / (Vector A, double p)
 40 {
 41     return Vector(A.x/p, A.y/p);
 42 }
 43 
 44 bool operator < (const Point& a, const Point& b)
 45 {
 46     return a.x < b.x || (a.x == b.x && a.y < b.y);
 47 }
 48 
 49 int dcmp(double x)
 50 {
 51     if(fabs(x) < eps)
 52         return 0;
 53     else
 54     return x < 0 ? -1 : 1;
 55 }
 56 
 57 bool operator == (const Point& a, const Point& b)
 58 {
 59     return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
 60 }
 61 
 62 double Dot(Vector A, Vector B)
 63 {
 64     return A.x * B.x + A.y * B.y;
 65 }
 66 
 67 double Cross(Vector A, Vector B)
 68 {
 69     return A.x * B.y - A.y * B.x;
 70 }
 71 
 72 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)
 73 {
 74     Vector u = P - Q;
 75     double t = Cross(w, u) / Cross(v, w);
 76     return P + v * t;
 77 }
 78 
 79 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
 80 {
 81     double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1),
 82            c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);
 83     return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
 84 }
 85 
 86 bool OnSegment(Point p, Point a1, Point a2)
 87 {
 88     return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
 89 }
 90 
 91 Point P[N], V[N*N];
 92 
 93 int main()
 94 {
 95     int n, cas = 0;
 96     while(~scanf("%d",&n) && n)
 97     {
 98         for(int i = 0; i < n; i++)
 99         {
100             scanf("%lf%lf", &P[i].x, &P[i].y);
101             V[i] = P[i];
102         }
103         n--;
104         int vcnt = n, ecnt = n;
105         for(int i = 0; i < n; i++)
106             for(int j = i + 1; j < n; j++)
107             {
108                 if(SegmentProperIntersection(P[i], P[i+1], P[j], P[j+1]))
109                     V[vcnt++] = GetLineIntersection(P[i], P[i+1]-P[i], P[j], P[j+1]-P[j]);
110             }
111         sort(V, V+vcnt);
112         vcnt = unique(V, V+vcnt) - V;//去掉相邻元素中重复的,使用前先排序
113         for(int i = 0; i < vcnt; i++)
114             for(int j = 0; j < n; j++)
115                 if(OnSegment(V[i], P[j], P[j+1]))
116                     ecnt++;
117         int ans = ecnt + 2 - vcnt;
118         printf("Case %d: There are %d pieces.\n", ++cas, ans);
119     }
120     return 0;
121 }
View Code

 

uvalive 3263 That Nice Euler Circuit

标签:

原文地址:http://www.cnblogs.com/ITUPC/p/4868608.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!