SGU 209 Areas(直线将平面分成封闭图形的面积)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=209

题意:给出一些直线。这些直线将平面分成好多块。求这些块中各个封闭图形的面积。

思路:求出所有交点。任意两个交点之间有直接的边相连则这两个点连一条边(两条双向边),并为每个边编号。搜封闭图形时每次找最左侧的。





int DB(double x)

{

    if(x>1e-10) return 1;

    if(x<-1e-10) return -1;

    return 0;

}





class point

{

public:

    double x,y;



    point(){}

    point(double _x,double _y)

    {

        x=_x;

        y=_y;

    }



    void get()

    {

        RD(x,y);

    }



    point operator+(point a)

    {

        return point(x+a.x,y+a.y);

    }



    point operator-(point a)

    {

        return point(x-a.x,y-a.y);

    }



    double operator*(point a)

    {

        return x*a.y-y*a.x;

    }



    point operator*(double t)

    {

        return point(x*t,y*t);

    }



    double operator^(point a)

    {

        return x*a.x+y*a.y;

    }



    double getLen()

    {

        return sqrt(x*x+y*y);

    }



    point operator/(double t)

    {

        return point(x/t,y/t);

    }



    double getAng(point a)

    {

        return atan2(*this*a,*this^a);

    }



    int operator==(const point &a) const

    {

        return DB(x-a.x)==0&&DB(y-a.y)==0;

    }



    int operator<(const point &a) const

    {

        if(DB(x-a.x)) return x<a.x;

        return y<a.y;

    }



    void print()

    {

        printf("%.6lf %.6lf\n",x,y);

    }

};



const int N=85;

point L[N][2];

vector<point> p,G[N];

vector<pair<int,int> > g[N*N*N];

int visit[N*N*N];

int n;



int isParal(point a,point b,point p,point q)

{

    double x=(b.x-a.x)*(q.y-p.y);

    double y=(b.y-a.y)*(q.x-p.x);

    return !DB(x-y);

}



point getCross(point a,point b,point p,point q)

{

    double s1=(a-p)*(b-p);

    double s2=(b-q)*(a-q);

    return (p*s2+q*s1)/(s1+s2);

}



int cmp(point a,point b)

{

    if(DB(a.x-b.x)) return a.x<b.x;

    return a.y<b.y;

}



int m;

map<point,int> Map;

point x,y;



double cross(point a,point b,point p)

{

    return (b-a)*(p-a);

}



int cmp1(pair<int,int> A,pair<int,int> B)

{

    point a=p[A.first];

    point b=p[B.first];

    double xx=cross(x,y,a);

    double yy=cross(x,y,b);

    if(DB(xx)!=DB(yy)) return DB(xx)>DB(yy);

    xx=(a-y).getAng(x-y);

    yy=(b-y).getAng(x-y);

    return DB(xx-yy)<0;

}



void build()

{

    int i,j,k,t,x=0;

    FOR1(i,n)

    {

        for(j=0;j+1<SZ(G[i]);j++)

        {

            k=Map[G[i][j]];

            t=Map[G[i][j+1]];

            if(k==t) continue;

            g[k].pb(MP(t,++x));

            g[t].pb(MP(k,++x));

        }

    }

}



vector<double> s;



void calArea(vector<int> a)

{

    double ans=0;

    int i;

    point x,y;

    a.pb(a[0]);

    for(i=0;i+1<SZ(a);i++)

    {

        x=p[a[i]];

        y=p[a[i+1]];

        ans+=x*y;

    }

    ans=fabs(ans)/2;

    s.pb(ans);

}





void DFS(int cur,int pre,vector<int> temp,int t)

{

    if(cur==t)

    {

        calArea(temp);

        return;

    }

    temp.pb(cur);

    int i,j,k;

    x=p[pre];

    y=p[cur];

    sort(g[cur].begin(),g[cur].end(),cmp1);

    for(i=0;i<SZ(g[cur]);i++)

    {

        j=g[cur][i].first;

        k=g[cur][i].second;

        if(j==pre||visit[k]) continue;

        if(DB(cross(p[pre],p[cur],p[j]))<=0) return;

        visit[k]=1;

        DFS(j,cur,temp,t);

        return;

    }

}



void cal()

{

    vector<int> temp;

    int i,j,k,t;

    for(i=0;i<m;i++)

    {

        for(j=0;j<SZ(g[i]);j++)

        {

            k=g[i][j].first;

            t=g[i][j].second;

            if(visit[t]||j&&g[i][j-1].first==k) continue;

            visit[t]=1;

            temp.clear();

            temp.pb(i);

            DFS(k,i,temp,i);

        }

    }

    sort(s.begin(),s.end());

    PR(SZ(s));

    FOR0(i,SZ(s)) printf("%.8lf\n",s[i]);

}



int main()

{

    RD(n);

    int i,j,k;

    point temp;

    FOR1(i,n)

    {

        L[i][0].get();

        L[i][1].get();

        for(j=1;j<i;j++)

        {

            if(isParal(L[j][0],L[j][1],L[i][0],L[i][1])) continue;

            temp=getCross(L[j][0],L[j][1],L[i][0],L[i][1]);



            for(k=0;k<SZ(G[i]);k++) if(G[i][k]==temp) break;

            if(k>=SZ(G[i]))  G[i].pb(temp);

            for(k=0;k<SZ(G[j]);k++) if(G[j][k]==temp) break;

            if(k>=SZ(G[j]))  G[j].pb(temp);



            p.pb(temp);

        }

    }

    sort(p.begin(),p.end(),cmp);

    m=unique(p.begin(),p.end())-p.begin();

    FOR0(i,m) Map[p[i]]=i;

    FOR1(i,n) sort(G[i].begin(),G[i].end(),cmp);

    build();

    cal();

}

  

你可能感兴趣的:(AS)