求解最近公共点对

  给出位于平面坐标系上的n个点,找到一对点使得这对点的距离尽可能的小,求这个最小的距离是多少。

  如果这些点是在一维情况下很容易想到分治,ans=min(solve(l,mid),solve(mid+1,r),temp),temp显然是dis(p[i],p[j])(i点为处于S1集合且最靠近中线的点,j是处于S2集合最靠近中线的点),跨越两个点集又使得距离最小只能是中间的两个点了,还有一个显然的推论是:如果ans=temp,就说明i,j两点到中线的距离一定都小于d'=min(solve(l,mid),solve(mid+1,r));

  对于二维的情况,同样我们筛去的点是横坐标距离中线大于d'的点,可以看出选这些点一定不会优于d'。也就是说我们检查的点如下图所示:

  //S下方的点是待检查点

  对于这些待检查点如果直接暴力的话还是不可行,万一待检查点数目过多得话复杂度还是接近于N^2,还是不行,我们可以缩小遍历范围。(前提是分治求出了d')

 对于SL区域下内所有点,任意两点间距必定不小于d',SR也同理,所以如果我们在SL(SR)区域内画出一个d'*2d'的矩形的话,这个矩形内最多只有六个点,也就是下面这图(b)这种情况:

 具体证明不怎么会= =

那么同理我们可以推出在S内画出一个2d'*2d'的矩形的话,矩形内不会超过12个点,也就是说我们对于S内的点按照y坐标升序排列之后,只需遍历每个点上面的十二个点就好了,超过这个数的点一定在矩形之外,纵坐标之差大于d',一定不会是最优解了。这样的话复杂度就降低很多。

  例题: https://www.nowcoder.com/acm/contest/59/E

  要求的就是<i,pre[i]>最大的距离平方。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 const LL INF=1LL<<62;
 5 struct Point
 6 {
 7     LL x,y;
 8     Point(){}
 9     Point(LL _x,LL _y):x(_x),y(_y){}
10 }p[101000],q[101000];
11 int pre[101000];
12 bool cmpx(Point A,Point B){return A.x<B.x;}
13 bool cmpy(Point A,Point B){return A.y<B.y;}
14 LL dis(Point A,Point B){return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}
15 LL solve(int left,int right)
16 {
17     if(left>=right) return INF;
18     if(left+1==right) return dis(p[left],p[right]);
19     int mid=(left+right)>>1;
20     LL res=min(solve(left,mid),solve(mid+1,right));
21     int s=0;
22     for(int i=left;i<=right;++i){
23         if(p[i].x>=p[mid].x-res&&p[i].x<=p[mid].x+res) q[s++]=p[i];
24     }
25     sort(q,q+s,cmpy);
26     for(int i=0;i<s;++i){
27         for(int j=i+1;j<s&&j-i<10;++j){
28             if(q[j].y-q[i].y>=res) break;
29             res=min(res,dis(q[i],q[j]));
30         }
31     }
32     return res;
33 }
34 int main()
35 {
36     int n,i,j,k,x;
37     while(cin>>n){
38         for(i=1;i<=n;++i){
39             scanf("%d",&x);
40             pre[i]=pre[i-1]+x;
41             p[i]=Point(i,pre[i]);
42         }
43         sort(p+1,p+1+n,cmpx);
44         printf("%lld
",solve(1,n));
45     }
46     return 0;
47 }
原文地址:https://www.cnblogs.com/zzqc/p/8370747.html