[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 }

 

posted @ 2018-10-26 19:38  HocRiser  阅读(329)  评论(0编辑  收藏  举报