zoukankan      html  css  js  c++  java
  • 平面最近点对问题

    平面上(n)个点,求距离最近的两个点的距离。

    通过分治求解。把所有点按(x)排序,每次从最中间的那个点分开(设其横坐标为(M)),递归求解左右两区域的最近点对,再求跨过中线的最近点对。

    设递归左右区域后,当前答案为(d),显然:
    1.如果想让(d)变小,就要找到距离(leq d)的点对,所以只用考虑横坐标与中线相差不超过(d)的点。
    2.左右两区域内的点,两两距离(geq d)

    枚举左区域中的点((a,b)),需要考虑的右边的点只有横坐标不超过(M+d),纵坐标在([b-d,b+d])内的点。考虑在一个(d*2d)的矩形内塞尽量多的点,使得两两距离(geq d),这样的点最多有六个,所以整个算法的时间复杂度(O(nlog n))

    CF429D

    一个长度为(n)的序列(a),定义(f(l,r)=(r-l)^2+(sum_{i=l+1}^r a_i)^2),求(f(l,r))的最小值。

    明显就是(n)个点((i,s_i))求个最近点对。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define mid ((l+r)>>1)
    using namespace std;
    typedef long long LL;
    const int mxn=100010;
    struct nd{
    	int x,y;
    	bool operator<(const nd a)const{
    		return y<a.y;
    	}
    }a[mxn],b[mxn];
    int n;
    LL ans;
    LL dis(nd x,nd y){
    	return 1ll*(x.x-y.x)*(x.x-y.x)+1ll*(x.y-y.y)*(x.y-y.y);
    }
    void solve(int l,int r){
    	if (l==r) return;
    	int M=a[mid].x;
    	solve(l,mid),solve(mid+1,r);
    	int d=sqrt(ans),cur=1,m=0;
    	for (int i=mid+1;i<=r;++i)
    		if (a[i].x<=M+d) b[++m]=a[i];
    	for (int i=l;i<=mid;++i)
    		if (a[i].x>=M-d){
    			for (;cur<=m&&b[cur].y<a[i].y-d;++cur);
    			for (int j=cur;j<=m&&b[j].y<=a[i].y+d;++j) ans=min(ans,dis(a[i],b[j]));
    		}
    	int pa=l,pb=mid+1,p=l;
    	for (;pa<=mid&&pb<=r;)
    		if (a[pa]<a[pb]) b[p++]=a[pa++];
    		else b[p++]=a[pb++];
    	for (;pa<=mid;b[p++]=a[pa++]);
    	for (;pb<=r;b[p++]=a[pb++]);
    	for (int i=l;i<=r;++i) a[i]=b[i];
    }
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1,x,s=0;i<=n;++i)
    		scanf("%d",&x),a[i]=(nd){i,s+=x};
    	ans=1e18;
    	solve(1,n);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    多层感知机的简洁实现
    汇编语言总结(1)
    回顾下TCP/IP协议
    五笔输入法的前世今生
    大O算法
    算法基础概念
    TCP和UDP的区别
    数据结构基本概念和术语
    gdb调试方法
    GD32F20x系列使用问题总结
  • 原文地址:https://www.cnblogs.com/zzqtxdy/p/12401553.html
Copyright © 2011-2022 走看看