• BZOJ 2458: [BeiJing2011]最小三角形 | 平面分治


    题目:

    给出若干个点

    求三个点构成的周长最小的三角形的周长(我们认为共线的三点也算三角形)


    题解:

    可以参考平面最近点对的做法

    只不过合并的时候改成枚举三个点更新周长最小值,其他的和最近点对大同小异

    2#include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define N 200010
    #define INF 1e20
    using namespace std;
    int n;
    struct point
    {
        double x,y;
        point () {};
        point (double _x,double _y)
    	{
    	    x=_x,y=_y;
    	}
        point operator - (const point &a)const
    	{
    	    return point(x-a.x,y-a.y);
    	}
        bool  operator < (const point &a)const
    	{
    	    return x<a.x;
    	}
        double norm()
    	{
    	    return sqrt(x*x+y*y);
    	}
    }p[N];
    double calc(const point &x,const point &y,const point &z)
    {
        return (x-y).norm()+(y-z).norm()+(x-z).norm();
    }
    double solve(int l,int r)
    {
        if (r==l) return INF;
        int mid=l+r>>1;
        double xmid=(p[mid].x+p[mid+1].x)/2;
        double ret=min(solve(l,mid),solve(mid+1,r));
        static point a[N],b[N],c[N];
        int pos=l,i=l,j=mid+1,b_n=0,c_n=0;
        while (pos<=r)
        {
    	if (i<=mid && (p[i].y<p[j].y || j>r))
    	{
    	    if (p[i].x+ret/2>xmid)
    		b[++b_n]=p[i];
    	    a[pos++]=p[i++];
    	}
    	else
    	{
    	    if (p[j].x-ret/2<xmid)
    		c[++c_n]=p[j];
    	    a[pos++]=p[j++];
    	}
        }
        for (i=l;i<=r;i++)
    	p[i]=a[i];
        if (r-l<2) return INF;
        /*
          for (int i=1;i<=b_n;i++)
          for (int j=i+1;j<=b_n;j++)
          for (int k=1;k<=c_n;k++)
          if (i!=j) ret=min(ret,(b[i]-b[j]).norm()+(b[i]-c[k]).norm()+(b[j]-c[k]).norm());
          for (int i=1;i<=b_n;i++)
          for (int j=1;j<=c_n;j++)
          for (int k=j+1;k<=c_n;k++)
          if (j!=k) ret=min(ret,(b[i]-c[j]).norm()+(b[i]-c[k]).norm()+(c[j]-c[k]).norm());
        */
        //  /*
        for (int i=1,j=1;i<=b_n;i++)
        {
    	while (j<=c_n && b[i].y-c[j].y>ret/2) j++;
    	for (int k=j;k<=c_n && abs(b[i].y-c[k].y)<ret/2;k++)
    	    for (int h=k+1;h<=c_n && abs(b[i].y-c[h].y)<ret/2;h++)
    		ret=min(ret,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>ret/2) j++;
    	for (int k=j;k<=b_n && abs(c[i].y-b[k].y)<ret/2;k++)
    	    for (int h=k+1;h<=b_n && abs(c[i].y-b[h].y)<ret/2;h++)
    		ret=min(ret,calc(c[i],b[k],b[h]));
        }
        //  */
        return ret;
    }
    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+1+n);
        printf("%.6lf",solve(1,n));
        return 0;
    }
    
  • 相关阅读:
    内部类
    this关键字
    封装
    构造方法
    类图
    StringBuffer
    String
    导包
    包名规范
    带参数的方法
  • 原文地址:https://www.cnblogs.com/mrsheep/p/8051404.html
Copyright © 2020-2023  润新知