Codeforces problem 67E(多边形求内核的应用)

题目:E. Save the City!

 

/*

Goujinping 2013.4.12  NEFU

The masterplate of Polygon kernel.

Now the global variable Area stand for the area of Polygon  kernel

In most case,the problem let us judge whether the Polygon kernel
exist or not and calculate the area,perimeter,or other constants
about the Polygon kernel.

*/

#include <math.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>

using namespace std;

const int N=11111;
const double EPS = 1e-8;

typedef double DIY;

DIY Area,Length;

struct Point
{
    DIY x,y;
    Point() {}
    Point(DIY _x,DIY _y):x(_x),y(_y) {}
} p[N];

Point MakeVector(Point &P,Point &Q)
{
    return Point(Q.x-P.x,Q.y-P.y);
}

DIY CrossProduct(Point P,Point Q)
{
    return P.x*Q.y-P.y*Q.x;
}

DIY MultiCross(Point P,Point Q,Point R)
{
    return CrossProduct(MakeVector(Q,P),MakeVector(Q,R));
}

struct halfPlane
{
    Point s,t;
    DIY angle;
    halfPlane() {}
    halfPlane(Point _s,Point _t):s(_s),t(_t) {}
    halfPlane(DIY sx,DIY sy,DIY tx,DIY ty):s(sx,sy),t(tx,ty) {}
    void GetAngle()
    {
        angle=atan2(t.y-s.y,t.x-s.x);
    }
} hp[N],q[N];

Point IntersectPoint(halfPlane P,halfPlane Q)
{
    DIY a1=CrossProduct(MakeVector(P.s,Q.t),MakeVector(P.s,Q.s));
    DIY a2=CrossProduct(MakeVector(P.t,Q.s),MakeVector(P.t,Q.t));
    return Point((P.s.x*a2+P.t.x*a1)/(a2+a1),(P.s.y*a2+P.t.y*a1)/(a2+a1));
}

bool cmp(halfPlane P,halfPlane Q)
{
    if(fabs(P.angle-Q.angle)<EPS)
        return MultiCross(P.s,P.t,Q.s)>0;
    return P.angle<Q.angle;
}

bool IsParallel(halfPlane P,halfPlane Q)
{
    return fabs(CrossProduct(MakeVector(P.s,P.t),MakeVector(Q.s,Q.t)))<EPS;
}

void HalfPlaneIntersect(int n,int &m)
{
    sort(hp,hp+n,cmp);
    int i,l=0,r=1;
    for(m=i=1; i<n; ++i)
        if(hp[i].angle-hp[i-1].angle>EPS) hp[m++]=hp[i];
    n=m; m=0;
    q[0]=hp[0];q[1]=hp[1];
    for(i=2; i<n; i++)
    {
        if(IsParallel(q[r],q[r-1])||IsParallel(q[l],q[l+1])) return;
        while(l<r&&MultiCross(hp[i].s,hp[i].t,IntersectPoint(q[r],q[r-1]))>0) --r;
        while(l<r&&MultiCross(hp[i].s,hp[i].t,IntersectPoint(q[l],q[l+1]))>0) ++l;
        q[++r]=hp[i];
    }
    while(l<r&&MultiCross(q[l].s,q[l].t,IntersectPoint(q[r],q[r-1]))>0) --r;
    while(l<r&&MultiCross(q[r].s,q[r].t,IntersectPoint(q[l],q[l+1]))>0) ++l;
    q[++r]=q[l];
    for(i=l; i<r; ++i)
        p[m++]=IntersectPoint(q[i],q[i+1]);
}

void Solve(Point *p,int n,int &m)
{
    int i,j;
    Point a,b;
    p[n]=p[0];
    for(i=0;i<n;i++)
    {
        hp[i]=halfPlane(p[(i+1)%n],p[i]);
        hp[i].GetAngle();
    }
    a=p[0],b=p[1];
    HalfPlaneIntersect(n,m);

    Area=0;Length=0;

    if(m>2)
    {
        if(a.x>b.x) swap(a,b);
        int f2=0,f1=0;
        for(int i=0; i<m; i++)
        {
            if(p[i].y==a.y&&p[(i+1)%m].y==a.y)
            {
                f2=1;
                a=p[i];
                b=p[(i+1)%m];
                break;
            }
            else if(p[i].y==a.y)
                f1=1;
        }
        if(f1&&!f2)
            Length=1;
        else if(f2)
        {
            if(a.x>b.x)
                swap(a,b);
            Length=(int)(b.x-a.x)+1;
        }
    }

    if(m>2)
    {
        p[m]=p[0];
        for(i=0;i<m;++i)
            Area+=CrossProduct(p[i],p[i+1]);
        if(Area<0) Area=-Area;
    }
    Area/=2.0;
}

int main()
{
    int n,m;
    while(cin>>n)
    {
        for(int i=0; i<n; i++)
            cin>>p[i].x>>p[i].y;
        Solve(p,n,m);
        cout<<Length<<endl;
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值