zoukankan      html  css  js  c++  java
  • [bzoj] 2458 最小三角形 || 平面分治

    原题

    求平面内周长最小的三角形。


    平面分治板子题。
    设当前最小为d,我们要求跨过分治线的三角形:
    把所有距离线不超过d/2的点加入(因为大于d/2那么所在的三角形一定周长大于d,不必考虑),对于每个两个点,考虑同侧距离不超过d/2的点。
    而要求在同一侧的三角形只要递归进行即可。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define N 200010
    using namespace std;
    int n;
    struct hhh
    {
        double x,y;
        bool operator < (const hhh &b) const
    	{
    	    return x<b.x;
    	}
        friend hhh operator - (const hhh &a,const hhh &b)
    	{
    	    return (hhh){a.x-b.x,a.y-b.y};
    	}
        inline double ds() const
    	{
    	    return sqrt(x*x+y*y);
    	}
    }p[N],a[N],b[N],c[N];
    
    double calc(hhh x,hhh y,hhh z)
    {
        return (x-y).ds()+(y-z).ds()+(z-x).ds();
    }
    
    double solve(int l,int r)
    {
        if (l==r) return 1e20;
        int mid=(l+r)>>1;
        double mid_x=(p[mid].x+p[mid+1].x)/2;
        double d=min(solve(l,mid),solve(mid+1,r));
        int pos=l,ll=l,rr=mid+1,b_n=0,c_n=0;
        while (pos<=r)
        {
    	if (ll<=mid && (rr>r || p[ll].y<p[rr].y))
    	{
    	    if (p[ll].x>mid_x-d/2) b[++b_n]=p[ll];
    	    a[pos++]=p[ll++];
    	}
    	else
    	{
    	    if (p[rr].x<mid_x+d/2) c[++c_n]=p[rr];
    	    a[pos++]=p[rr++];
    	}
        }
        for (int i=l;i<=r;i++) p[i]=a[i];
        if (r-l<2) return 1e20;
        for (int i=1,j=1;i<=b_n;i++)
        {
    	while (j<=c_n && b[i].y-c[j].y>d/2) j++;
    	for (int k=j;k<=c_n && abs(b[i].y-c[k].y)<d/2;k++)
    	    for (int h=k+1;h<=c_n && abs(b[i].y-c[h].y)<d/2;h++)
    		d=min(d,calc(b[i],c[k],c[h]));
        }
        for (int i=1,j=1;i<=c_n;i++)
        {
    	while (j<=b_n && c[i].y-b[j].y>d/2) j++;
    	for (int k=j;k<=b_n && abs(c[i].y-b[k].y)<d/2;k++)
    	    for (int h=k+1;h<=b_n && abs(c[i].y-b[h].y)<d/2;h++)
    		d=min(d,calc(c[i],b[k],b[h]));
        }
        return d;
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
    	scanf("%lf%lf",&p[i].x,&p[i].y);
        sort(p+1,p+n+1);
        printf("%.6lf
    ",solve(1,n));
        return 0;
    }
    
  • 相关阅读:
    C++-蓝桥杯-颠倒的价牌[2013真题][水题][模拟]
    C++-蓝桥杯-振兴中华[2013真题][水题][dp/递归]
    C++-蓝桥杯-排它平方数[2013][水题][枚举]
    C++-蓝桥杯-高斯日记[2013真题][水题][枚举模拟]
    C++-蓝桥杯-购物清单[2017真题][水题][文件输入]
    C++-蓝桥杯-九宫幻方[暴力搜索][无剪枝]
    C++-LUOGU3834 可持久化线段树(主席树)[模板]
    BASIC-2 01字串
    【掌大】关注回复
    【掌大】纸飞机
  • 原文地址:https://www.cnblogs.com/mrha/p/8034665.html
Copyright © 2011-2022 走看看