• UVA12001 UVa Panel Discussion 题解


    原题链接:UVA12001 UVa Panel Discussion

    题目大意:给定平面上的(n)个点,询问两两之间距离的最小值((n le 10000)且当答案(> 10000)时输出( ext{INFINITY}))。


    题解:看到这题我的第一反应是建 k-D Tree 然后再暴力找到距离每个点最近的点,时间复杂度应该是期望(O(nsqrt{n})),然后发现(O(n^2))只差一点,暴力改改其实就能过了,但是,这一题的数据范围貌似是可以放到(10^5),那么这个时候就需要找到一个更加高效的算法。

    考虑对平面上的点分治,每次按照 x 轴切成两半,左右递归处理,接下来只需要处理跨过中间线的点对就可以了,然而暴力处理并不能让这一道题的时间复杂度更优,考虑利用左右两侧的答案进行剪枝。

    假设当前的答案为(ans),那么显然离中间线的距离超过(ans)的点可以不用处理了,对于一个点((x_i,y_i)),我们只需要处理(y)的范围在(y_i-ans<y<=y_i)的点就可以了(同 x 轴的方法一样)。

    接下来就是一个很像 CDQ 分治的东西,这样,递归的深度为(O(log n)),每一层有期望(O(n))个操作,所以总的时间复杂度是期望(O(nlog n))

    下面放代码:

    #include <cmath>
    #include <vector>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int Maxn=10000;
    struct Node{
    	double x,y;
    	friend bool operator <(Node p,Node q){
    		if(p.y==q.y){
    			return p.x<q.x;
    		}
    		return p.y<q.y;
    	}
    }a[Maxn+5];
    bool cmp(Node p,Node q){
    	if(p.x==q.x){
    		return p.y<q.y;
    	}
    	return p.x<q.x;
    }
    int n;
    double ans;
    void calc(int left,int right){
    	if(left==right){
    		return;
    	}
    	int mid=(left+right)>>1;
    	double line=(a[mid].x+a[mid+1].x)/2;
    	calc(left,mid);
    	calc(mid+1,right);
    	inplace_merge(a+left,a+1+mid,a+1+right);
    	vector<Node> b;
    	for(int i=left;i<=right;i++){
    		if(fabs(a[i].x-line)>=ans){
    			continue;
    		}
    		for(int j=(int)b.size()-1;j>=0;j--){
    			double dx=a[i].x-b[j].x;
    			double dy=a[i].y-b[j].y;
    			if(dy>=ans){
    				break;
    			}
    			ans=min(ans,sqrt(dx*dx+dy*dy));
    		}
    		b.push_back(a[i]);
    	}
    }
    int main(){
    	while(~scanf("%d",&n)){
    		if(n==0){
    			break;
    		}
    		for(int i=1;i<=n;i++){
    			scanf("%lf%lf",&a[i].x,&a[i].y);
    		}
    		sort(a+1,a+1+n,cmp);
    		ans=10001;
    		calc(1,n);
    		if(ans>10000.0){
    			puts("INFINITY");
    		}
    		else{
    			printf("%.4lf
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    洛谷 [SDOI2015]约数个数和 解题报告
    multiset-count
    multiset-begin
    multiset-begin
    set-value_comp
    set-value_comp
    multiset-constructors
    multiset-constructors
    set-upper_bound
    set-upper_bound
  • 原文地址:https://www.cnblogs.com/withhope/p/12873341.html
Copyright © 2020-2023  润新知