ZOJ 3762 Pan's Labyrinth

比赛过程中想到了算法,但是没有敲,事后想到可以直接套模版了...


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define op operator
#define cp const Point&
using namespace std;
const double eps = 1e-8, pi = acos(-1.0);
const int N = 505;
inline int sig(double x){return (x>eps)-(x<-eps);}
inline double sqr(double x){return x*x;}

struct Point{
    double x,y,ang;
    void in(){scanf("%lf%lf",&x,&y);}
    Point(){}
    Point(double xx,double yy):x(xx),y(yy){}
    Point op+(cp a)const{return Point(x+a.x,y+a.y);}
    Point op-(cp a)const{return Point(x-a.x,y-a.y);}
    double op^(cp a)const{return x*a.y-y*a.x;}
    double cross(cp a,cp b){return (a-*this)^(b-*this);}
    bool op<(cp a)const{return x<a.x || (x==a.x && y<a.y);}
    double angle(){return atan2(y,x)+pi;}
    double L(){return sqrt(sqr(x)+sqr(y));}
} pnt[N],res[N],rot[N];

bool cmp(cp a,cp b){return a.ang<b.ang;}
double ptoline(Point p,Point a,Point b){
    return fabs(p.cross(a,b))/(a-b).L();
}

int Graham(Point *p,int n,Point *ch){
    sort(p,p+n);
    int m=0;
    for(int i=0;i<n;++i){
        while(m>1 && sig((ch[m-1]-ch[m-2])^(p[i]-ch[m-1]))<0) --m;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;--i){
        while(m>k && sig((ch[m-1]-ch[m-2])^(p[i]-ch[m-1]))<0) --m;
        ch[m++]=p[i];
    }
    if(m>1) --m;
    return m;
}

double check(int k,int n,int m){
    double ret=0;
    int cnt=0;
    for(int i=0;i<n;++i){
        if(i!=k){
            rot[cnt]=pnt[i]-pnt[k];
            rot[cnt].ang=rot[cnt].angle();
            ++cnt;
        }
    }
    sort(rot,rot+cnt,cmp);
    int j=0;
    while(1){
        if(sig(rot[0]^(res[j]-pnt[k]))>=0 &&
           sig(rot[0]^(res[(j+m-1)%m]-pnt[k]))<=0) break;
        j=(j+1)%m;
    }
    for(int i=0;i<cnt;++i){
        Point tmp=pnt[k]+rot[i];
        while(ptoline(res[j+1],pnt[k],tmp)>ptoline(res[j],pnt[k],tmp) ||
              sig(ptoline(res[j],pnt[k],tmp))==0) j=(j+1)%m;
        ret=max(ret,ptoline(res[j],pnt[k],tmp));
    }
    return ret;
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;++i) pnt[i].in();
        int m=Graham(pnt,n,res);
        double ans=0;res[n]=res[0];
        for(int i=0;i<n;++i)
            ans=max(ans,check(i,n,m));
        printf("%.10lf\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值