• [BZOJ]2458: [BeiJing2011]最小三角形


    题目大意:给出平面上n个点,求最小的由这些点组成的三角形的周长。(N<=200,000)

    思路:点按x坐标排序后分治,每次取出与排在中间的点的横坐标相差不超当前答案一半的点,按y坐标排序后再暴力枚举y坐标相差不超过当前答案一半的三个点统计答案,复杂度O(能过)(听说期望nlogn)。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x,f=1;char c;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=-1;
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x*f;
    }
    #define MN 200000
    double ans=1e18;
    struct P{int x,y;}p[MN+5],t[MN+5];
    bool cmpx(P a,P b){return a.x<b.x;}
    bool cmpy(P a,P b){return a.y<b.y;}
    double sqr(double x){return x*x;}
    double len(P a,P b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
    void solve(int l,int r)
    {
        if(r-l<2)return;
        int m=l+r>>1,i,j,k,cnt=0;
        solve(l,m);solve(m+1,r);
        for(i=l;i<=r;++i)if(fabs(p[i].x-p[m].x)<ans/2)t[++cnt]=p[i];
        sort(t+1,t+cnt+1,cmpy);
        for(i=1;i<=cnt;++i)for(j=i+1;j<=cnt&&t[j].y-t[i].y<ans/2;++j)for(k=j+1;k<=cnt&&t[k].y-t[i].y<ans/2;++k)
            ans=min(ans,len(t[i],t[j])+len(t[j],t[k])+len(t[k],t[i]));
    }
    int main()
    {
        int n=read(),i;
        for(i=1;i<=n;++i)p[i].x=read(),p[i].y=read();
        sort(p+1,p+n+1,cmpx);
        solve(1,n);
        printf("%.6lf",ans);
    }
  • 相关阅读:
    HDU1864--01背包
    HDU4508--完全背包
    HDU5410--01背包+完全背包
    HDU1284--完全背包
    HDU1248--完全背包
    HDU2191--多重背包(二进制分解+01背包)
    HDU2186--水
    PAT乙级--1003
    51Nod--1006 lcs
    51Nod--1008
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ2458.html
Copyright © 2020-2023  润新知