[BJWC2011]最小三角形(平面最近点对)

传送门

题意:平面上有N个点,找出周长最小的三角形.注意:这里的三角形也包括共线的三点.

分析:回忆一下平面最近点对问题:平面上有N个点,找出距离最近的两个点.显然,本题唯一的不同之处在于要找三个点.所以我们仍然可以套平面最近点对问题的板子,只是稍微修改一下递归边界,注意一下求距离的时候是求三个点两两之间距离之和就可以了.

最后提醒一下,本题爆int.

蒟蒻的平面最近点对学习笔记

LL n,b[200005];
struct point{
    LL x,y;
}a[200005];
bool cmpx(point x,point y){return x.x<y.x;}
bool cmpy(const LL &x,const LL &y){return a[x].y<a[y].y;}
double pf(LL x){return x*x*1.0;}
double dis(point x,point y,point z){
    return sqrt(pf((x.x-y.x))+pf((x.y-y.y)))+sqrt(pf((x.x-z.x))+pf(x.y-z.y))+sqrt(pf((y.x-z.x))+pf(y.y-z.y));
}
double solve(LL l,LL r){
    if(l+1>=r)return 1e18;
    if(l+2==r)return dis(a[l],a[l+1],a[r]);
//注意一下求三个点与两个点的边界条件不同
    LL mid=(l+r)>>1;
    double midline=(a[mid].x+a[mid+1].x)/2;
    double d=min(solve(l,mid),solve(mid+1,r));
    LL cnt=0;
    for(int i=l;i<=r;i++)
		if(fabs(a[i].x-midline)<=d)
        	b[++cnt]=i;
    sort(b+1,b+cnt+1,cmpy);
    for(int i=1;i<cnt;i++)
	for(int j=i+1;j<cnt;j++){
	    if((a[b[j]].y-a[b[i]].y)>d)break;
//不符合要求需要直接break掉,下面同理
//如果只是if(符合要求)...这样就会超时.
	    for(int k=j+1;k<=cnt;k++){
			if((a[b[k]].y-a[b[j]].y)>d)break;
			double dist=dis(a[b[i]],a[b[j]],a[b[k]]);
			if(dist<d)d=dist;
	    }
	}
    return d;
}
signed main(){
    n=read();
    for(int i=1;i<=n;i++){
		a[i].x=read();
		a[i].y=read();
    }
    sort(a+1,a+n+1,cmpx);
    printf("%.6lf\n",solve(1,n));
    return 0;
}

posted on 2019-02-12 14:44  PPXppx  阅读(350)  评论(0编辑  收藏  举报