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;
}
原文地址:https://www.cnblogs.com/luyouqi233/p/8033150.html