LA 3263 That Nice Euler Circuit 好看的一筆畫 幾何問題

LA 3263 好看的一筆畫

平面上有一個包含n個頂點的一筆畫,讓求閉合曲線形成的圖形將整個平面分成了幾部分。


解題思路:

1,首先這題要轉換思路利用到歐拉定理

歐拉定理:設平面圖的頂點數、邊數、和麪數分別爲V、E、F則V+F-E=2

那麼面數爲F = E+2-V

2,理解定理之後接下來的處理就是,記錄相交生成的交點,刪除重複的交點

3,最後就是求出有多少條線段、如果一個點出現在一個線段上(除了端點)、那麼就多加一條邊

4,用了《訓練指南》上的模版,感覺這樣寫非常好


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 310 ;
struct Point{
    double x,y ;
    Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector ;
Point P[maxn] ;
Point V[maxn*maxn] ;
bool operator < (const Point& a, const Point& b) {///排序:x自然排序,y自然排序
  return a.x < b.x || (a.x == b.x && a.y < b.y);
}
Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
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);}
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x ;}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y ;}
const double eps = 1e-10 ;
int dcmp(double x){
    if(fabs(x)<eps)return 0;
    else return x<0?-1:1 ;
}
bool operator == (const Point& a, const Point &b) {///這個函數是unique函數中重載了==符號
  return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){
    double c1 = Cross(a2-a1,b1-a1) ;
    double c2 = Cross(a2-a1,b2-a1) ;
    double c3 = Cross(b2-b1,a1-b1) ;
    double c4 = Cross(b2-b1,a2-b1) ;
    return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0 ;
}
bool OnSegment(Point p,Point a1,Point a2){return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0 ;}
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){
    Vector u = P-Q ;
    double t = Cross(w,u)/Cross(v,w) ;
    return P+v*t ;
}
int main(){
    int cas = 1 ;
    int n ;
    while(~scanf("%d",&n),n){
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&P[i].x,&P[i].y);
            V[i] = P[i] ;
        }
        n-- ;///最後一個點和第一個點相同
        int c = n ;
        int e = n ;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(SegmentProperIntersection(P[i],P[i+1],P[j],P[j+1])){///判斷任意兩條線段是否相交
                    V[c++] = GetLineIntersection(P[i],P[i+1]-P[i],P[j],P[j+1]-P[j]);///如果相交了就獲得一個交點
                }
            }
        }
        sort(V,V+c) ;///對點進行排序
        c = unique(V,V+c)-V ;///除去相同的點,返回值是不重複的元素最後一個元素的地址
        for(int i=0;i<c;i++){///對於一個點,如果他在另外的一條線段上出現,那麼這條線段就相當於被分爲兩段
            for(int j=0;j<n;j++){
                if(OnSegment(V[i],P[j],P[j+1])){
                    e++ ;
                }
            }
        }
        printf("Case %d: There are %d pieces.\n",cas++ ,e+2-c);
    }
    return 0;
}


發佈了104 篇原創文章 · 獲贊 3 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章