zoukankan      html  css  js  c++  java
  • BZOJ2458:[BJOI2011]最小三角形——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2458

    Description

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

    Input

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

    Output

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

    Sample Input

    4
    1 1
    2 3
    3 3
    3 4

    Sample Output

    3.414214

    HINT

    100%的数据中N≤200000。

    ————————————————

    哇作为练手平面分治的题我好高兴,一次A了。

    不过最开始怀疑自己的思路有问题于是查了题解……然后发现竟然是对的。

    额……

    复述一下,和平面分治差不多,将solve函数的含义改为当前区间内最小三角形的周长。

    然后我们发现对于一个三角形两点之间长度最大为d/2。

    所以我们在归并排序y的时候把和中轴距离d/2的点捡出来。

    然后三重循环枚举搞定(同时距离d/2不要忘了)

    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef double dl;
    const dl INF=1e20;
    const int N=200001;
    inline int read(){
        int X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        dl x;
        dl y;
    }p[N],a[N],b[N];
    bool cmp(node A,node B){
        return A.x<B.x;
    }
    inline dl dis(int i,int j){
        return sqrt(pow(b[i].x-b[j].x,2)+pow(b[i].y-b[j].y,2));
    }
    dl solve(int l,int r){
        if(l>=r)return INF;
        int mid=(l+r)>>1;
        dl x0=(p[mid].x+p[mid+1].x)/2.0;
        dl d=min(solve(l,mid),solve(mid+1,r));
        int l1=l,r1=mid+1,num=0;
        for(int i=l;i<=r;i++){
        if(l1<=mid&&(r1>r||p[l1].y<p[r1].y)){
            a[i]=p[l1++];
            if(x0-d/2<a[i].x)b[++num]=a[i];
        }else{
            a[i]=p[r1++];
            if(a[i].x<x0+d/2)b[++num]=a[i];
        }
        }
        for(int i=l;i<=r;i++)p[i]=a[i];
    
        for(int i=1;i<=num;i++){
        for(int j=i+1;j<=num;j++){
            if(b[j].y-b[i].y>=d/2)break;
            for(int k=j+1;k<=num;k++){
            if(b[k].y-b[j].y>=d/2)break;
            d=min(d,dis(i,j)+dis(j,k)+dis(k,i));
            }
        }
        }
        return d;
    }
    int main(){
        int n=read();
        for(int i=1;i<=n;i++){
        p[i].x=read();
        p[i].y=read();
        }
        sort(p+1,p+n+1,cmp);
        printf("%.6f
    ",solve(1,n));
        return 0;
    }
  • 相关阅读:
    C# 获得word中某一段落所在页的页码
    写一个安全的Java单例
    递归算法
    redis连接池连接失败的问题
    A query was run and no Result Maps were found for the Mapped Statement .....................
    解决maven默认JDK1.5报错
    mybatis控制台不报错数据库却没有值返回的问题
    LNMP 环境更换Nginx 服务器为Tengine
    简易的phpexcel导出柱状图
    Laravel学习基础篇之--路由
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8033150.html
Copyright © 2011-2022 走看看