UVALive 3263 二维几何基础

题意

给一笔画的N个点,问一笔画能分出多少块图形

题解

用欧拉定理,顶点数+面数-边数=2。顶点数把所有直线暴力两两相交,然后去重即可。枚举所有点,如果一个点在一条直线上,并且这个点不是端点,那么就一定是交点,这个交点把直线分成了两部分。因此可以暴力枚举点,对于每条直线,每枚举到一个交点,边数++。

注意事项

需要特别注意的是,题目的数据好像有些问题。网上大部分代码都是参考刘汝佳的蓝书,所以大部分人都没有提到线段覆盖的问题。但是实际测试发现,尽管题目明确指出了不存在线段覆盖的情况,如果特判线段覆盖(没有使用刘汝佳模板)就能AC,否则就会WA。

代码

#include<bits/stdc++.h>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(t) while(t)
#define MEM(a,b) memset(a,b,sizeof(a))
#define LL long long
#define INF 0x3f3f3f3f
#define EPS 1e-10
#define MAXN 1010
#define MOD 1000000007
#define COUT(x) cout<<x<<endl
using namespace std;
double sqr(double x) {
    return x*x;
}
int sgn(double x) {
    return x<-EPS?-1:x>EPS;
}
struct Point {
    double x,y;
    Point(double x=0,double y=0):x(x),y(y) {}
    friend Point operator + (const Point &a,const Point &b) {
        return Point(a.x+b.x,a.y+b.y);
    }
    friend Point operator - (const Point &a,const Point &b) {
        return Point(a.x-b.x,a.y-b.y);
    }
    friend Point operator * (const Point &a,const double &b) {
        return Point(a.x*b,a.y*b);
    }
    friend Point operator / (const Point &a,const double &b) {
        return Point(a.x/b,a.y/b);
    }
    friend Point operator * (const double &a,const Point &b) {
        return Point(b.x*a,b.y*a);
    }
    double norm() {
        return sqrt(sqr(x)+sqr(y));
    }
    friend double det(const Point &a,const Point &b) {
        return a.x*b.y-a.y*b.x;
    }
    friend double dot(const Point &a,const Point &b) {
        return a.x*b.x+a.y*b.y;
    }
    bool operator < (const Point b) {
        return sgn(x-b.x)<0||(sgn(x-b.x)==0&&sgn(y-b.y)<0);
    }
    bool operator == (const Point b) {
        return sgn(x-b.x)==0&&sgn(y-b.y)==0;
    }
};

struct Line {
    Point s,t;
    Line(Point s=Point(),Point t=Point()):s(s),t(t) {}
    Point vec() {
        return t-s;
    }
    double norm() {
        return vec().norm();
    }
    bool pointOnLine(const Point &p) {
        return sgn(det(p-s,t-s))==0;
    }
    bool pointOnLineEx(const Point &p) {
        return pointOnLine(p)&&sgn(dot(p-s,p-t))<0;
    }
    bool pointOnSeg(Point p) {
        return pointOnLine(p)&&sgn(dot(p-s,p-t))<=0;
    }
    friend Point linexline(Line l1,Line l2) {
        double s1=det(l1.s-l2.s,l2.vec());
        double s2=det(l1.t-l2.s,l2.vec());
//        COUT(s1-s2);
        return (l1.t*s1-l1.s*s2)/(s1-s2);
    }
};
bool parallel(Line l1,Line l2) {
    return !sgn(det(l1.vec(),l2.vec()));
}
bool sameside(Line l,Point a,Point b) {
    return sgn(det(b-l.s,l.vec()))*sgn(det(a-l.s,l.vec()))>0;
}
bool isSegXSeg(Line l1,Line l2) {
    if(parallel(l1,l2)) return false;
    if(!sameside(l1,l2.s,l2.t)&&!sameside(l2,l1.s,l1.t)){
//        COUT("new");
        return true;
    }else return false;
}
Point points[510];
Point vc[25010];
int main() {
//    freopen("d:/in.txt","r",stdin);
//    freopen("d:/out1.txt","w",stdout);
    int n;
    int ks=1;
    W(~scanf("%d",&n)) {
        if(n==0) break;
        MEM(points,0);
        MEM(vc,0);
        int lnum=0;
        UP(i,0,n) {
            scanf("%lf%lf",&points[i].x,&points[i].y);
//            COUT(points[i].x<<" "<<points[i].y);
        }
        n--;
        UP(i,0,n) vc[i]=points[i];
        int cnum=n;
        UP(i,0,n) {
            UP(j,i+1,n) {
                Line l1=Line(points[i],points[i+1]);
                Line l2=Line(points[j],points[j+1]);
                if(isSegXSeg(l1,l2)) {
//                        COUT("good");
                    vc[cnum++]=linexline(l1,l2);
                }
            }
        }
        sort(vc,vc+cnum);
//        UP(i,0,cnum) COUT(vc[i].x<<" "<<vc[i].y)  ;
        int v=unique(vc,vc+cnum)-vc;
//        COUT(cnum);
//        COUT(e<<" "<<v);
        int e=n;
        UP(i,0,v) {
            UP(j,0,n) {
                Line l=Line(points[j],points[j+1]);
                if(l.pointOnLineEx(vc[i])) {
//                        COUT(i<<" "<<j);
                    e++;
                }
            }
        }
        printf("Case %d: There are %d pieces.\n",ks++,e+2-v);
    }
}

猜你喜欢

转载自blog.csdn.net/zhenlingcn/article/details/78218645
今日推荐