看了蒋学长的博客
我们定义一个函数设f(l,r)表示从第l个点到第r个点之间的最小三角形
然后每一次都二分区间求f(l,mid)f(mid+1,r)然后发现这样没有避免三角形跨过mid的情况
所以再枚举就可以辣
可以证明复杂度这里就不说了(我不会啊)
下面是代码
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define N 200003
#define INF 210000000000.0
using namespace std;
struct arr{
int x,y;
}a[N],num[N];
int n,i,test;
inline bool cmpx(const arr &a,const arr &b){
return a.x<b.x;
}
inline bool cmpy(const arr &a,const arr &b){
return a.y<b.y;
}
inline double dis(const arr &a,const arr &b){
double ans=sqrt((a.x-b.x)*1.*(a.x-b.x)+(a.y-b.y)*1.*(a.y-b.y));
return ans;
}
inline double work(int l,int r){
if(r-l<=1){
return INF;
}
if(l+2==r){
return dis(a[l],a[l+1])+dis(a[l],a[r])+dis(a[l+1],a[r]);
}
int mid=(l+r)>>1;
double d1=work(l,mid),d2=work(mid+1,r);
double D=min(d1,d2),ans=D,DD=D/2.0;
int cnt=0;
for(int i=l;i<=r;i++){
if(fabs(a[mid].x-a[i].x)<=DD){
num[++cnt]=a[i];
}
}
sort(num+1,num+cnt+1,cmpy);
for(int i=1;i<cnt-1;i++){
for(int j=i+1;j<cnt;j++){
if(num[j].y-num[i].y>DD){
break;
}
for(int k=j+1;k<=cnt;k++){
if(num[k].y-num[i].y>DD){
break;
}
double temp=dis(num[i],num[j])+dis(num[i],num[k])+dis(num[j],num[k]);
ans=min(ans,temp);
}
}
}
return ans;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
}
sort(a+1,a+n+1,cmpx);
printf("%.6lf",work(1,n));
return 0;
}
/*
in:
4
1 1
2 3
3 3
3 4
out:
3.414214
*/