1. 程式人生 > >杭電ACM第1007題——Quoit Design

杭電ACM第1007題——Quoit Design

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int SIZE = 100005;

typedef struct {
	double x;
	double y;  
}point;
point p[SIZE], c[SIZE]/*用作輔助陣列*/;

double getDistance(point &a, point &b){  /*求得兩點之間的距離*/
	return sqrt(pow(a.x - b.x, 2.0) + pow(a.y - b.y, 2.0));
}

bool cmpx(point &a, point &b){
	if (a.x == b.x)
		return a.y < b.y;
	return a.x < b.x;
}
bool cmpy(point &a, point &b){
	if (a.y == b.y)
		return a.x < b.x;
	return a.y < b.y;
}

inline double min(double a, double b, double c){
	a = a< b ? a : b;
	a = a< c ? a : c;
	return a;
}

inline double minDist(double a, double b){
	a=a<b?a:b;
	return a;
}

double divide_conquer(int low, int high) {/*分治法求最小距離*/
	double dis;
	if (low==high)
		return 0;
	else if (low+1 == high)  /*兩個數*/
		dis = getDistance(p[low], p[high]);
	else if (low+2 == high){/*三個數*/
		double temp1, temp2, temp3;
		temp1 = getDistance(p[low], p[low + 1]);
		temp2 = getDistance(p[low + 1], p[high]);
		temp3 = getDistance(p[low], p[high]);
		dis = min(temp1, temp2, temp3);
	}
	else{   /*大於三個數的情況*/
		double leftmin, rightmin;
		int mid = (low + high) / 2;
		int k= 0,i, j;

		leftmin = divide_conquer(low, mid);  /*求得左邊部分的最小值*/
		rightmin = divide_conquer(mid + 1, high);  /*求得右邊部分的最小值*/
		dis = minDist(leftmin, rightmin);

		/*下面從所有座標點中找出所有x在leftCoord到rightCoord之間的點*/
		for (i = low; i <=high; i++){
			if (fabs(p[i].x-p[mid].x)<dis)
				c[k++]=p[i];
		}
		sort(c, c + k, cmpy);   /*找到的點再從小到大按照y排序一次*/
		for (i = 0; i < k; i++){
			for (j = i+1;j<k&&p[j].y-p[i].y<dis ; j++){	
				dis= minDist(dis,getDistance(c[i], c[j]));
			}
		}
	}
	return dis;
}

int main (){
	int n;
	while (cin >> n && n != 0){
		double result = 0;
		
		for (int i = 0; i < n; i++){
			cin >> p[i].x >> p[i].y;
		}
		sort (p, p + n, cmpx);
		result = divide_conquer(0, n - 1);
		printf("%.2lf\n", result / 2);
	}
	return 0;
}