[BZOJ2458][BeiJing2011]最小三角形(分治)
求平面上n个点组成的周长最小的三角形。
回忆平面最近点对的做法,找到横坐标的中点mid分治到两边,合并时考虑离mid横坐标不超过当前最小值d的所有点,按y排序后暴力更新答案。
这个题也一样,先分治到两边,然后取出所有离mid横坐标不超过当前最小值/2的点,按y排序后选择三个总坐标不超过当前最小值/2的点更新答案。
按y排序在递归上来时归并,复杂度O(nlogn)。
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 using namespace std; 7 8 const int N=200010; 9 int n; 10 double ans=1e10; 11 struct P{ int x,y; }p[N],p2[N]; 12 bool cmp(const P &a,const P &b){ return a.x<b.x; } 13 double sqr(double x){ return x*x; } 14 double dis(int a,int b){ return sqrt(sqr(p[a].x-p[b].x)+sqr(p[a].y-p[b].y)); } 15 16 void solve(int l,int r){ 17 if (r<=l) return; 18 if (r-l==1){ if (p[l].y>p[r].y) swap(p[l],p[r]); } 19 int mid=(l+r)>>1,tmp=p[mid].x; 20 solve(l,mid); solve(mid+1,r); 21 for (int i=l,j=mid+1,w=l-1; i<=mid || j<=r; ) 22 if ((i<=mid) && (j>r || p[j].y>p[i].y)) p2[++w]=p[i++]; else p2[++w]=p[j++]; 23 rep(i,l,r) p[i]=p2[i]; 24 rep(i,l+2,r) if (2*abs(p[i].x-tmp)<=ans) 25 for (int j=i-2; j>=l && 2*(p[i].y-p[j].y)<=ans; j--) 26 if (2*abs(p[j].x-tmp)<=ans) 27 rep(k,j+1,i-1) ans=min(ans,dis(i,j)+dis(j,k)+dis(i,k)); 28 } 29 30 int main(){ 31 freopen("bzoj2458.in","r",stdin); 32 freopen("bzoj2458.out","w",stdout); 33 scanf("%d",&n); 34 rep(i,1,n) scanf("%d%d",&p[i].x,&p[i].y); 35 sort(p+1,p+n+1,cmp); 36 solve(1,n); printf("%.6lf\n",ans); 37 return 0; 38 }