Poj 2284 That Nice Euler Circuit
生活随笔
收集整理的這篇文章主要介紹了
Poj 2284 That Nice Euler Circuit
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
人生第一道正兒八經的計算幾何題。。。光消編譯錯誤就弄了老半天,果然是夠弱。。
題意大概是,給你N條線段,它們會構成一個一筆畫的圖形,給你先線段的順序就是一筆畫的順序,線段可能相交但是不會重合
問你最后那個圖形可以將平面分成多少個區域(包括有窮區域和無窮區域)
顯然這里可以利用歐拉定理來求解,即平面上的點數+面數=邊數+2
那么問題就轉化為求最后的圖形有多少個點和多少條邊了。
大體思路是,通過枚舉線段來求出所有線段的交點,加上原有題目告訴你的所有線段的起點和終點,可以求得圖中所有的點的數量。
但是因為有可能出現三點共線的情況,這樣會導致多余的點的出現,因此求出所有的點之后對點集做一次去重處理,可以利用STL里面的unique函數,非常的方便
然后枚舉每一個新增的交點,如果這個交點在一個線段之間,那么就會導致一條新邊的產生。
由此就完成了邊和點的統計
?
#include <cstdio> #include <algorithm> #include <cmath>#define INPUT_FILE "in.txt" #define OUTPUT_FILE "out.txt"using namespace std;typedef long long LL; const int maxn = 400; const double eps = 1e-10;void setfile() {freopen(INPUT_FILE,"r",stdin);freopen(OUTPUT_FILE,"w",stdout); }struct Point {double x,y;Point(double x = 0,double y = 0):x(x),y(y) {} };typedef Point Vector; Point v[maxn * maxn]; //頂點 Point p[maxn];Vector operator - (Point a,Point b) {return Vector(a.x - b.x,a.y - b.y); }Vector operator * (Vector a,double p) {return Vector(a.x * p,a.y * p); }Vector operator + (Vector a,Vector b) {return Vector(a.x + b.x,a.y + b.y); }double dot(Vector a,Vector b) {return a.x * b.x + a.y * b.y; }int dcmp(double x) {if(fabs(x) < eps) return 0;return x < 0 ? -1 : 1; }bool operator < (Point a,Point b) {return a.x < b.x || (a.x == b.x && a.y < b.y); }double cross(Vector a,Vector b) {return a.x * b.y - a.y * b.x; }bool have_intersection(Point a1,Point a2,Point b1,Point b2) {double c1 = cross(a2 - a1,b1 - a1),c2 = cross(a2 - a1,b2 - a1);double c3 = cross(b2 - b1,a1 - b1),c4 = cross(b2 - b1,a2 - b1);bool ret = (dcmp(c1) * dcmp(c2) < 0) && (dcmp(c3) * dcmp(c4) < 0);return ret; }bool on_segment(Point p,Point a,Point b) {return dcmp(cross(p - a,p - b)) == 0 && dcmp(dot(a - p,b - p)) < 0; }Point get_intersection(Point a1,Point a2,Point b1,Point b2) {Vector v = a2 - a1,w = b2 - b1,u = a1 - b1;double t = cross(w,u) / cross(v,w);return a1 + v * t; }bool operator == (Point a,Point b) {return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0; }int main() {int n,kase = 1;while(scanf("%d",&n),n) {for(int i = 0;i < n;i++) {scanf("%lf%lf",&v[i].x,&v[i].y);p[i] = v[i];}int cnt_v = n - 1,cnt_f = 0,cnt_e = n - 1; n--; //判斷一下給定的線段是否有交點for(int i = 0;i < n;i++) {for(int j = i + 1;j < n;j++) {if(have_intersection(p[i],p[i + 1],p[j],p[j + 1])) {//找到交點了就添加到點集里面v[cnt_v++] = get_intersection(p[i],p[i + 1],p[j],p[j + 1]);}}}//特判三點共線的時候的狀態sort(v,v + cnt_v);cnt_v = unique(v,v + cnt_v) - v;//處理因為線段交點而新生成的線段for(int i = 0;i < cnt_v;i++) {for(int j = 0;j < n;j++) {if(on_segment(v[i],p[j],p[j + 1])) {cnt_e++;}}}printf("Case %d: There are %d pieces.\n",kase++,2 + cnt_e - cnt_v);}return 0; }
轉載于:https://www.cnblogs.com/rolight/p/3691750.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Poj 2284 That Nice Euler Circuit的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# async await 学习笔记1
- 下一篇: 在ubuntu14.04 64位中使用j