POJ--2284--That Nice Euler Circuit【平面圖歐拉公式】
阿新 • • 發佈:2017-05-20
time 說明 pop 求交點 content for pro main long long
鏈接:http://poj.org/problem?id=2284
題意:一個自己主動繪圖的機器在紙上(無限大)繪圖,筆尖從不離開紙,有n個指令,每一個指令是一個坐標,由於筆尖不離開紙,所以相鄰的坐標會連有一條直線,最後畫筆再回到起始點。
所以這個圖是一個連通圖,而且畫筆走過的路徑是一個歐拉回路。
如今問題來了。這個圖形將平面分成了幾部分。
思路:題目說明確一些就是告訴你一些幾何信息問平面被分成了幾部分。能夠用歐拉公式來做
歐拉公式:如果圖的頂點個數為n,邊數為m,區域數位r,則有 n - m + r = 2,前提必須是連通圖
知道隨意兩個就能求第三個
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 90010 #define eps 1e-7 #define INF 0x3F3F3F3F //0x7FFFFFFF #define LLINF 0x7FFFFFFFFFFFFFFF #define seed 1313131 #define MOD 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct Point{ //點 double x, y; Point(double a = 0, double b = 0){ x = a; y = b; } }; struct LineSegment{ //線段 Point s, e; LineSegment(Point a, Point b){ s = a; e = b; } }; struct Line{ //直線 double a, b, c; }; bool operator < (Point p1, Point p2){ return (p1.x < p2.x || p1.x == p2.x) && p1.y < p2.y; } bool operator == (Point p1, Point p2){ return fabs(p1.x - p2.x) < eps && fabs(p1.y - p2.y) < eps; } bool Online(LineSegment l, Point p){ //推斷點是否在線段上 return fabs((l.e.x - l.s.x) * (p.y - l.s.y) - (p.x - l.s.x) * (l.e.y - l.s.y)) < eps && (p.x - l.s.x) * (p.x - l.e.x) < eps && (p.y - l.s.y) * (p.y - l.e.y) < eps; } Line MakeLine(Point p1, Point p2){ //將線段延長為直線 Line l; if(p2.y > p1.y){ l.a = p2.y - p1.y; l.b = p1.x - p2.x; l.c = p1.y * p2.x - p1.x * p2.y; } else{ l.a = p1.y - p2.y; l.b = p2.x - p1.x; l.c = p1.x * p2.y - p1.y * p2.x; } return l; //返回直線 } bool LineIntersect(Line l1, Line l2, Point &p){ //推斷直線是否相交。並求出交點p double d = l1.a * l2.b - l2.a * l1.b; if(fabs(d) < eps) return false; //求交點 p.x = (l2.c * l1.b - l1.c * l2.b) / d; p.y = (l2.a * l1.c - l1.a * l2.c) / d; return true; } bool LineSegmentIntersect(LineSegment l1, LineSegment l2, Point &p){ //推斷線段是否相交 Line a, b; a = MakeLine(l1.s, l1.e), b = MakeLine(l2.s, l2.e); //將線段延長為直線 if(LineIntersect(a, b, p)) //假設直線相交 return Online(l1, p) && Online(l2, p); //推斷直線交點是否在線段上,是則線段相交 else return false; } bool cmp(Point a, Point b){ if(fabs(a.x - b.x) < eps) return a.y < b.y; else return a.x < b.x; } Point p[MAXN], Intersection[MAXN]; int N, m, n; int main(){ int i, j, cas = 1; while(scanf("%d", &N), N){ m = n = 0; for(i = 0; i < N; i++){ scanf("%lf%lf", &p[i].x, &p[i].y); } for(i = 0; i < N; i++){ for(j = 0; j < N; j++){ LineSegment l1(p[i], p[(i + 1) % N]), l2(p[j], p[(j + 1) % N]); Point p; if(LineSegmentIntersect(l1, l2, p)) Intersection[n++] = p; //記錄交點 } } sort(Intersection, Intersection + n, cmp); n = unique(Intersection, Intersection + n) - Intersection; for(i = 0; i < n; i++){ for(j = 0; j < N; j++){ LineSegment t(p[j], p[(j + 1) % N]); if(Online(t, Intersection[i]) && !(t.s == Intersection[i])) //若有交點落在邊上,則該邊分裂成兩條邊 m++; } } printf("Case %d: There are %d pieces.\n", cas++, 2 - n + m); } return 0; }
POJ--2284--That Nice Euler Circuit【平面圖歐拉公式】