SGU315:The Highway Belt(DP)

来源:互联网 发布:收银机什么软件好 编辑:程序博客网 时间:2024/06/16 05:56

传送门(Vjudge)

题意:
给n条线段,用这些线段中的一些围成一个围绕原点的多边形,满足原点发出任意射线与此多边形只有一个交点。求满足条件的多边形的最大周长。(n50)

题解:

写了一种O(n6)的DP,但是上界是很不满的,所以卡一卡就过去了。。

首先求出所有线段的两端点和交点(用map判重),之后每条线段上的点都向逆时针方向所有在该线段上的点连边。

现在相当于求一个最大简单环,用Floyed方法暴力DP(需要剪枝)。

#include<bits/stdc++.h>using namespace std;inline int read(){    char ch=getchar();int i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return i*f;}const double INF=1e9;const double eps=1e-9;const int Maxn=1e3+5e2+50;typedef pair<double,double> pii;inline int sgn(double x){    return (int)(x>eps)-(x<-eps);}struct point{    double x,y;    point(double x=0,double y=0):x(x),y(y){}    friend inline point operator -(const point &a,const point &b){return point(a.x-b.x,a.y-b.y);}    friend inline double operator *(const point &a,const point &b){return a.x*b.y-a.y*b.x;}    inline double norm(){return sqrt(x*x+y*y);}    friend inline bool operator <(const point &a,const point &b){        int t=sgn(b.x-a.x);        if(t)return t>0;        else return (sgn(b.y-a.y)>0);     } }p[Maxn];struct line{    point a,b;    line(){}    line(point a,point b):a(a),b(b){}}l[Maxn];inline point insert(const line &a,const line &b){    double k1=(a.b-b.a)*(a.a-b.a);    double k2=(a.a-b.b)*(a.b-b.b);    double t=((k1)/(k1+k2));    return point(b.a.x+(b.b.x-b.a.x)*t,b.a.y+(b.b.y-b.a.y)*t);}inline bool in(const point &a,const line &b){    return (a.x+eps>min(b.a.x,b.b.x))&&((a.x-eps<max(b.a.x,b.b.x)))&&(a.y+eps>min(b.a.y,b.b.y))&&(a.y-eps<max(b.a.y,b.b.y)); }int n,tot,slope[Maxn];map<point,int>S_p;vector<int>pre[Maxn];vector<int>pre2[Maxn];vector<int>line_p[Maxn];int is[55][Maxn];double f[Maxn][Maxn],d[Maxn][Maxn],ans;inline bool cmp_slope(const point &a,const point &b){    double t1=atan2(a.y,a.x),t2=atan2(b.y,b.x);    return t1<t2;}inline bool exi(const point &a,const point &b){    for(int i=1;i<=n;i++){        if(fabs((l[i].a-a)*(l[i].b-a))>eps)continue;        if(!in(a,l[i]))continue;        if(fabs((l[i].a-b)*(l[i].b-b))>eps)continue;        if(!in(b,l[i]))continue;        return true;    }    return false;}int main(){    n=read();     for(int i=1;i<=n;i++){        point a,b;        a.x=read(),a.y=read();b.x=read(),b.y=read();        if(!S_p.count(a))S_p.insert(make_pair(a,++tot)),p[tot]=a;        if(!S_p.count(b))S_p.insert(make_pair(b,++tot)),p[tot]=b;        l[i]=line(a,b);        for(int j=1;j<i;j++){            point q=insert(l[i],l[j]);            if(!in(q,l[i])||!in(q,l[j]))continue;            if(!S_p.count(q))S_p.insert(make_pair(q,++tot)),p[tot]=q;        }    }    sort(p+1,p+tot+1,cmp_slope);    for(int i=1;i<=n;i++){        for(int j=1;j<=tot;j++){            if(fabs((l[i].a-p[j])*(l[i].b-p[j]))>eps)continue;            if(in(p[j],l[i]))line_p[i].push_back(j);        }    }    for(int i=1;i<=tot;i++)        for(int j=1;j<=tot;j++)            f[i][j]=(d[i][j]=(i==j?0:-INF));    for(int i=1;i<=n;i++){        int sz=line_p[i].size()-1;        for(int t1=0;t1<=sz;++t1){            for(int t2=0;t2<=sz;++t2){                if(t1==t2)continue;                int tt1=line_p[i][t1],tt2=line_p[i][t2];                if(p[tt1]*p[tt2]<eps)continue;                d[tt1][tt2]=(p[tt1]-p[tt2]).norm();                pre[tt2].push_back(tt1);            }        }    }    static int vis[Maxn],vt;    for(int i=1;i<=tot;i++){        ++vt;        f[i][i]=0;pre2[i].push_back(i);        for(int k=pre[i].size()-1;k>=0;k--){            int K=pre[i][k];            for(int j=pre2[K].size()-1;j>=0;j--){                int J=pre2[K][j];                f[J][i]=max(f[J][i],f[J][K]+d[K][i]);                if(vis[J]!=vt)vis[J]=vt,pre2[i].push_back(J);            }           }        for(int j=1;j<tot;j++){            if(d[i][j])ans=max(ans,f[j][i]+d[i][j]);        }    }    (ans>eps)?printf("%.5f\n",ans):puts("0");}