closest pair 알고리즘 문제 관련 질문했던 사람입니다.
      글쓴이: canuyes / 작성시간: 일, 2013/06/16 - 4:35오후    
  
  저번 질문에 코드가 너무 정리가 안되어 있어서 나름대로 좀더 정리해서 코드를 올려봅니다.
이번에는 100000개의 인풋에 대해 1초 안에 실행되기는 하지만, 메모리 128mb 메모리를 초과하네요...
제 코드에서 128mb 이내 1초 이내에 10만개의 인풋을 모두 처리하려면 어디를 개선해야 할까요?.
#include<iostream>
#include<cstdlib>
#include<cstring>
#define MAX_DIST 1000000000
using namespace std;
struct DOT{int x;int y;};
DOT xet[100000];
DOT yet[100000];
//정렬시에 사용될 함수입니다.
inline int comp_x(const void* A,const void* B){return ((DOT*)A)->x-((DOT*)B)->x;}
inline int comp_y(const void* A,const void* B){return ((DOT*)A)->y-((DOT*)B)->y;}
//두 값중 작은 값을 리턴하는 함수입니다.
inline int smaller(const int A,const int B){if(A<B){return A;}return B;}
//두점 사이의 거리를 계산하는 함수입니다.
inline int DIST(const DOT A,const DOT B){return ((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
//점의 갯수가 8개 이하일때, 단순하게 O(n^2)으로 답을 구합니다.
inline int brute_force(DOT* arr,int size){
	int i,j,ret=MAX_DIST;
	for(i=0;i<size-1;i++){for(j=i+1;j<size;j++){ret=smaller(ret,DIST(arr[i],arr[j]));}}
	return ret;
}
//답을 만들어내는 함수입니다.
inline int mkANS(DOT* xet,DOT* yet,int size){
	int ret=MAX_DIST;
	//점의 갯수가 8개 이하일 경우 brute_force를 호출합니다.
	if(size<9){ret=brute_force(xet,size);}
	else{
		//pivot에 x축 기준으로 가운댓 점의 x좌표를 대입합니다.
		int i,dist,L=-1,R=size,pivot=xet[size/2].x;
		//yyet를 생성하여 pivot보다 x좌표가 작은 점은 yyet의 왼쪽에,
		//pivot보다 x좌표가 큰점은 오른 쪽에 저장합니다.
		//이때, y축 기준으로 정렬된 yet 순차적으로 저장하므로
		//yyet의 왼,오른 쪽은 자동으로 y축 오름 차순으로 정렬됩니다.
		DOT* yyet=new DOT[size];
		for(i=0;i<size;i++){
			if(yet[i].x-pivot<=0){yyet[++L]=yet[i];}
			else{yyet[--R]=yet[i];}
		}
		//왼쪽 점의 갯수,오른쪽 점의 갯수를 알아 내었으므로 왼쪽 오른 쪽에 대해 다시 재귀 호출합니다.
		ret=smaller(mkANS(xet,yet,L+1),mkANS(xet+L+1,yet+L+1,size-L-1));
		//위에서 구해진 왼쪽 점끼리로만 만들어진 최소거리와 오른 쪽점들로만 만들어진 최소거리중 더 작은 값으로 부터
		//pivot에서 위의 값이내에 들어오는 점들을 yyet에 왼쪽부터 차례로 대입합니다.
		//이때 역시 yet를 순차적으로 탐색하므로 yyet에는 자동적으로 y축에 대해 정렬된 값들이 저장됩니다.
		L=-1;
		for(i=0;i<size;i++){
			dist=(yet[i].x-pivot)*(yet[i].x-pivot);
			if(dist>=ret){continue;}
			else{yyet[++L]=yet[i];}
		}
		//왼쪽, 오른쪽을 가로 지르는 경우, y축 오름차순으로 이웃하는 점끼리만 고려해주면 되므로
		//아래의 비교를 수행합니다.
		for(i=0;i<=L-1;i++){ret=smaller(ret,DIST(yyet[i],yyet[i+1]));}
		delete []yyet;
	}
	return ret;
}
int main(void){
	int i,N;cin>>N;
	for(i=0;i<N;i++){cin>>xet[i].x>>xet[i].y;}
	memcpy(yet,xet,sizeof(DOT)*N);
	//xet에 x축 기준으로 정렬하여 저장합니다.
	qsort(xet,N,sizeof(DOT),comp_x);
	//yet에 y축 기준으로 정렬하여 저장합니다.
	qsort(xet,N,sizeof(DOT),comp_y);
	cout<<mkANS(xet,yet,N)<<endl;
	return 0;
}나름대로 주석을 달아 봤습니다.
아래는 실행시간 1초 128mb 메모리 이내에서 실행된 정답 코드입니다.
제가 작성한 코드가 아니기에 링크 남깁니다.
http://rosettacode.org/wiki/Closest-pair_problem/C
제가 작성한 코드와 큰 차이는 없어보이는데, 어디서 이러한 차이가 발생하는 것인가요?
궁금합니다. 
Forums: 


알고리즘이 어떻게 돌아가는지 모르겠습니다. 단,
알고리즘이 어떻게 돌아가는지 모르겠습니다.
단, 올려주신 코드와 정답(?) 코드에 차이는
mkANS 함수에서 smaller/closest를 찾을 때 입니다.
정답 코드는 이분해서 좌우를 찾지만, 올려주신 코드는 항상 L=-1인 상태로 전체 검색을 하는거 같습니다.
그리고, 그 부분만 수정되면 올려주신 코드가 아마도 훨씬 빠를겁니다.
이유는 sqrt를 사용하지 않아서 입니다.
(물론, int를 사용하셔서 거리^2가 int의 범위를 넘지 않을까 걱정도 됩니다.)
댓글 달기