UVALive 3263 && POJ 2284 That Nice Euler Circuit (欧拉定理+计算几何)

 

 给出 n 个点,将其连成一个回路,问这些线段将平面分成几部分

根据欧拉定理,平面数 ans=边数-顶点数+2

所以只需要利用计算机和基础计算顶点数和边数即可

因为所连的线是由给定的顺序产生的,所以可以从前面按照顺序枚举,两两相邻的点作为一条边,判断是否产生交点

由于可能产生多线共点的情况,再进行去重。

最后判断每一个点再几条边上,这样线段内的一个点将一条线段分为两条线段 

const int N=300+5;

    int i,j,k;
    int n,m,t;
    struct Point
    {
        double x,y;
        Point(double x=0,double y=0):x(x),y(y){}
    }a[N];
typedef Point Vector;
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; }
Vector operator-(Vector a,Vector b){ return Vector(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*(double k,Vector a){ return Vector(k*a.x,k*a.y); }
bool operator<(const Vector a,const Vector b)
{
    return a.x<b.x || (a.x==b.x && a.y<b.y);
}
bool operator==(const Vector a,const Vector b)
{
    return a.x==b.x && a.y==b.y;
}
vector<Point> v;

int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    return x>0?1:-1; 
}

bool judge(Point a1,Point a2,Point b1,Point b2)
{
    double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1);
    double d1=Cross(b2-b1,a1-b1),d2=Cross(b2-b1,a2-b1);
    return sgn(c1)*sgn(c2)<0 && sgn(d1)*sgn(d2)<0;
}

Point get_interpoint(Point a,Vector u,Point b,Vector v)
{
    Vector w=b-a;
    double t=Cross(w,v)/Cross(u,v);
    return a+t*u; 
}

bool Online(Point p,Point a,Point b)
{
    return sgn(Cross(a-p,b-p))==0 && sgn(Dot(a-p,b-p))<0; 
}

int main()
{
    //IOS;
    int num=0;
    while(~sd(n),n){
        v.clear();
        for(int i=1;i<=n;i++) sff(a[i].x,a[i].y),v.pb(a[i]);
        for(int i=1;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(judge(a[i],a[i+1],a[j],a[j+1])){
                    Point tmp=get_interpoint(a[i],a[i+1]-a[i],a[j],a[j+1]-a[j]);
                    v.pb(tmp);
                }
            }
        }
        int edge=n-1;
        sort(v.begin(),v.end());
        int vcnt=unique(v.begin(),v.end())-v.begin();
        for(int i=0;i<vcnt;i++){
            for(int j=1;j<n;j++){
                if(Online(v[i],a[j],a[j+1])) edge++;
            }
        }
        int ans=edge+2-vcnt;
        printf("Case %d: There are %d pieces.\n",++num,ans);
    }
    //PAUSE;
    return 0;
}

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页