• bzoj2458 最小三角形


    Description

    Xaviera现在遇到了一个有趣的问题。
    平面上有N个点,Xaviera想找出周长最小的三角形。
    由于点非常多,分布也非常乱,所以Xaviera想请你来解决这个问题。
    为了减小问题的难度,这里的三角形也包括共线的三点。

    Input

    第一行包含一个整数N表示点的个数。
    接下来N行每行有两个整数,表示这个点的坐标。

    Output

    输出只有一行,包含一个6位小数,为周长最短的三角形的周长(四舍五入)。

    首先旋转坐标系防止被卡。
    将点排序,分割为左右/上下两部分,对每个子问题分别排序,直至子问题足够小时暴力枚举。
    利用子问题求得的当前最优解ans缩小范围,将两个子问题在分界直线两侧距离<ans/2的点进行枚举。
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    double ans=1.0e16;
    int w=0;
    struct pos{
        double x[2];
    }ps[200010];
    bool operator<(const pos &a,const pos &b){
        return a.x[w]<b.x[w];
    }
    double dist(pos &a,pos &b){
        double x=a.x[0]-b.x[0],y=a.x[1]-b.x[1];
        return sqrt(x*x+y*y);
    }
    void f(int _w,int l,int r){
        if(l+20>r){
            for(int i=l;i<r;i++)
            for(int j=i+1;j<r;j++)
            for(int k=j+1;k<=r;k++){
                double v=dist(ps[i],ps[j])+dist(ps[i],ps[k])+dist(ps[j],ps[k]);
                if(v<ans)ans=v;
            }
            return;
        }
        w=_w;
        std::sort(ps+l,ps+r+1);
        int m=l+r>>1;
        f(_w^1,l,m);
        f(_w^1,m+1,r);
        w=_w;
        std::sort(ps+l,ps+m+1);
        std::sort(ps+m+1,ps+r+1);
        int p1=m,p2=m+1;
        int a=ans*0.5+1,x1=ps[m].x[_w],x2=ps[m+1].x[_w];
        while(p1>l&&ps[p1-1].x[_w]+a>=x1)--p1;
        while(p2<r&&ps[p2+1].x[_w]-a<=x2)++p2;
        w^=1;
        std::sort(ps+p1,ps+m+1);
        std::sort(ps+m+1,ps+p2+1);
        for(int i=p1;i<=m;i++){
        int p3=m+1,p4=p2;
        while(p3<p2&&ps[p3+1].x[w]+a<ps[i].x[w])++p3;
        while(p4>m+1&&ps[p4-1].x[w]-a>ps[i].x[w])--p4;
        for(int j=p3;j<p4;j++)
        for(int k=j+1;k<=p4;k++){
            double v=dist(ps[i],ps[j])+dist(ps[i],ps[k])+dist(ps[j],ps[k]);
            if(v<ans)ans=v;
        }
        }
        for(int i=m+1;i<=p2;i++){
        int p3=p1,p4=m;
        while(p3<p2&&ps[p3+1].x[w]+a<ps[i].x[w])++p3;
        while(p4>m+1&&ps[p4-1].x[w]-a>ps[i].x[w])--p4;
        for(int j=p3;j<p4;j++)
        for(int k=j+1;k<=p4;k++){
            double v=dist(ps[i],ps[j])+dist(ps[i],ps[k])+dist(ps[j],ps[k]);
            if(v<ans)ans=v;
        }
        }
    }
    int n;
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%lf%lf",&ps[i].x[0],&ps[i].x[1]);
        double c=cos(0.8),s=sin(0.8);
        for(int i=0;i<n;i++){
            double x=ps[i].x[0],y=ps[i].x[1];
            ps[i].x[0]=c*x+s*y;
            ps[i].x[1]=-s*x+c*y;
        }
        f(0,0,n-1);
        printf("%.6lf",ans);
        return 0;
    }
  • 相关阅读:
    oracle 调优3
    ifconfig找不到命令的帖子 精选
    执行计划中各字段各模块描述
    oracle统计信息
    oracle中 rownum与rowid的理
    触发器
    开园第一天
    Asp.net生成htm静态文件的两种途径
    避免刷新页面,自动跳回到页面顶部的办法
    ASP.NET二级域名站点共享Session状态
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5250467.html
Copyright © 2020-2023  润新知