好长一段时间没做题目了,主要是工作上比较忙,还要陪女朋友,但是算法是自己的一点小爱好,有时间还是要做题目的,就当换换脑子休息一下吧!哈哈!
–Divide: 整个问题划分为多个子问题–Conquer:求解各子问题(递归调用正设计的算法)–Combine:合并子问题的解, 形成原始问题的解
给你n个点,求出其中点与点之间的最短距离。
这个题目就是用上面的分治算法。将所有的点分为两部分,左边和右边,那么最短距离要么在左边,要么在右边,要么跨边界。
那么我们就可以递归了,如果只剩一个点,就返回一个超过10000的值,如果只有两个点,直接求距离。
那如果n个点,就分两部分,先递归求出左边最小值,右边最小值,然后求出二者的最小值min,然后枚举跨边界的的点的距离,这个时候我们只需要取两边距离小于min的就行,因为大于min的对我们的结果没有意义。
在这里我做了一下优化,就是代码中那个循环为何小于i+7,而不是cnt,其实cnt也行,只是浪费时间。实际上,我们找出距离边界的所有点,直接枚举两两之间的距离就行,和min作比较,返回最小值。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> struct POINT { double x,y; }point[10010],temp[10010]; double dis(struct POINT p1, struct POINT p2) { return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); } int cmp(const void * a, const void * b) { struct POINT * c = (struct POINT *)a; struct POINT * d = (struct POINT *)b; if (c->x != d->x) { return c->x > d->x; } else return c->y > d->y; } int cmp1(const void * a, const void * b) { struct POINT * c = (struct POINT *)a; struct POINT * d = (struct POINT *)b; if (c->y != d->y) { return c->y > d->y; } else return c->x > d->x; } double findMin(int l, int r) { if (l == r) { return 10010; } if (l == r - 1) { return dis(point[l], point[r]); } double tmp1 = findMin(l,(l + r) >> 1); double tmp2 = findMin(((l + r) >> 1) + 1, r); double Mindis,tmp, mid; mid = point[(l + r) >> 1].x; /*mid = (point[l].x + point[r].x) / 2.0;*/ int i,j,cnt = 0; if (tmp1 < tmp2) { Mindis = tmp1; } else Mindis = tmp2; for (i = l; i <= r; ++ i) { if (fabs(point[i].x - mid) < Mindis) { temp[cnt ++] = point[i]; } } qsort(temp, cnt, sizeof(temp[0]), cmp1); for (i = 0; i < cnt - 1; ++ i) { /*for (j = i + 1; j < cnt; ++ j)*/ for (j = i + 1; j < i + 7 && j < cnt; ++ j) { tmp = dis(temp[i], temp[j]); if (tmp < Mindis) { Mindis = tmp; } } } return Mindis; } int main() { int n,i,j; double minDis; while (scanf("%d", &n)==1 && n) { for (i = 0; i < n; ++ i) { scanf("%lf%lf", &point[i].x, &point[i].y); } qsort(point, n, sizeof(point[0]), cmp); minDis = findMin(0, n-1); if (minDis > 10000) { printf("INFINITY\n"); } else printf("%.4lf\n", minDis); } return 0; }