【详解】平面中最接近点对问题
来源:互联网 发布:牙签弩淘宝20¥ 编辑:程序博客网 时间:2024/06/03 21:11
数组当中的最接近点对问题详解
在一个一维数组当中要找出两个值相减得到的差值最小,当然有的人会说这个很简单,只要将数组当中的值两两相减,然后对最后的结果找一个最小值就可以了,这种方法想必是可以,这就是所谓的暴力解法,时间复杂度是非常大的。
我们这里我介绍一种时间复杂度比较低的算法,我们利用分治的策略,将大规模的问题缩小化,首先我们将数组平分一半,左边的数值均小于右边的数值,但是左边和右边分别是乱序的,不需要排序,然后找到左边的最接近点的值,右边最接近点的值,当然还有可能左边的最大值和右边的最小值的差也可能是最小值,将这三个值作比较取最小值也就是最接近点的差值,有人会问那么左边和右边的最小值怎么计算呢,这就是分治的妙处所在了,左边和右边跟原问题是一样了的,只是规模减小了,因此方法一样,代码一样,使用递归就可实现。
代码
const int MAXDISTENT = 0x7fffffff;int Select_K(int *ar, int left,int right, int k);int FindMax(int *ar, int left, int right){ int Max = ar[left]; for (int i = left; i < right; i++) { if (Max < ar[i]) { Max = ar[i]; } } return Max;}int FindMin(int *ar, int left, int right){ int Min = ar[left]; for (int i = left; i < right; i++) { if (Min > ar[i]) { Min = ar[i]; } } return Min;}int MyMin(int a, int b){ return a > b ? b : a;}int MyMin(int a, int b, int c){ return MyMin(MyMin(a, b), c);}int Cpair(int *ar, int left, int right){ if (right - left <= 0) return MAXDISTENT; int m = (right - left + 1)/2; Select_K(ar, left, right, m); int d1 = Cpair(ar, left, left+m - 1);//记得加left int d2 = Cpair(ar, left+m, right); int LMax = FindMax(ar, left, left+m - 1); int RMin = FindMin(ar, left+m, right); return MyMin(d1, d2, RMin-LMax);}int Cpair(int *ar, int len){ if (ar == NULL || len < 2) return MAXDISTENT; return Cpair(ar, 0, len - 1);}
平面中最接近点对问题详解
平面中最接近点对的求解和上述的思想是一样的,还是采用分治的思想,但是处理起来就比较麻烦了,主要是左边和右边的点的距离的计算,中线的划分就按照x排个序取中就是中线,y轴上是同样的道理,纵向的三根线围起来的部分之间的点距离均大于左边和右边的最小距离d,而6个小方格里面,每个小方格里面最多一个点,因此,每个点只需要和这方格里面的点算距离就是最小距离
代码
#define MAXFLOAT 3.14e38f;struct Point_X{ float x; float y; int id; operator float()const{ return x; }};struct Point_Y{ float x; float y; int p; operator float()const { return y; }};/////////////////////////////////////template<class Type>void Merge(Type *sd, Type *si, int left, int m, int right){ int i = left, j = m + 1; int k = left; while (i <= m && j <= right) { sd[k++] = si[i] < si[j] ? si[i++] : si[j++]; } while (i <= m) { sd[k++] = si[i++]; } while (j <= right) { sd[k++] = si[j++]; }}template<class Type>void Copy(Type *sd, Type *si, int left, int right){ for (int i = left; i <= right; ++i) { sd[i] = si[i]; }}template<class Type>void MergePass(Type *br, Type *ar, int left, int right){ if (left < right) { int m = (right - left) / 2 + left; MergePass(br, ar, left, m); MergePass(br, ar, m + 1, right); Merge(br, ar, left, m, right); Copy(ar, br, left, right); }}template<class Type>void MergeSort(Type *ar, int n){ Type *br = new Type[n]; MergePass(br, ar, 0, n - 1); delete[]br;}///////////////////////////////////void PrintPoint(Point_X *point, int num){ for (int i = 0; i < NUM; i++) { cout <<point[i].id<<"=》"<< point[i].x << setw(6) << point[i].y << endl; } cout << endl;}template<typename type>float Distance(const type &p1,const type &p2){ float dx = p1.x - p2.x; float dy = p1.y - p2.y; return sqrt(dx*dx + dy*dy);}float Closest(Point_X*X, Point_Y* Y, Point_Y*Z, int left,int right, Point_X&a, Point_X&b){ int num = right - left; if (num <= 0) return MAXFLOAT; if (num == 1) { a = X[left]; b = X[right]; return Distance(X[left], X[right]); } if (num == 2) { float dis1=Distance(X[left], X[left+1]); float dis2 = Distance(X[left + 1], X[left + 2]); float dis3 = Distance(X[left + 2], X[left]); if (dis1 < dis2&&dis1 < dis3) { a = X[left]; b = X[left+1]; return dis1; } if (dis2 < dis1&&dis2 < dis3) { a = X[left+1]; b = X[left+2]; return dis2; } else { a = X[left]; b = X[left+2]; return dis3; } } int m = (right - left) / 2 + left; //int z1 = left, m1 = m + 1; float d1 = Closest(X, Y,Z, left, m, a, b); Point_X a1, b1; float d2 = Closest(X, Y, Z, m + 1, right, a1, b1); float d = MAXFLOAT; if (d1 < d2) d = d1; else { d = d2; a = a1; b = b1; } //Merge(Y, Z, left, m, right); int k = left; for (int i = left; i < right;i++) { if (fabs(X[m].x - Y[i].x) < d) { Z[k++] = Y[i]; } } for (int i = left; i < k; i++) { for (int j = i + 1; j < k; j++) { if (fabs(Z[i].y - Z[j].y) >= d)//Z中本来就是按照Y排序的,因此一旦遇到比d大的后面也就都比d大 break; float d3 = Distance(Z[i], Z[j]); if (d3 > d) { a = X[Z[i].p]; b = X[Z[j].p]; d = d3; } } } return d;}float Cpair(Point_X*X, int num, Point_X &a, Point_X &b){ MergeSort(X, num); Point_Y *Y =new Point_Y[num]; for (int i = 0; i < num; i++) { Y[i].p = i; Y[i].x = X[i].x; Y[i].y = X[i].y; } Point_Y *Z = new Point_Y[num]; MergeSort(Y, num); float mindis = Closest(X, Y, Z, 0,num-1, a, b); return mindis;}
阅读全文
0 0
- 【详解】平面中最接近点对问题
- 【详解】平面中最接近点对问题
- 二维平面内最接近点对问题
- 最接近点对问题
- 最接近点对问题
- 最接近点对问题
- 最接近点对问题
- 最接近点对问题
- [luogu1429]平面最接近点对(二分)
- P1257 平面上的最接近点对
- 平面最近点对问题详解
- 最接近的点对问题
- 分治---最接近点对问题
- 乱搞一发: 平面上最接近点对 (COGS 1159)
- 【枚举】洛谷 P1257 平面上的最接近点对
- 洛谷Oj-平面上的最接近点对-分治
- 分治法--最接近点对问题
- 最接近点对问题(分治法)
- 之江学院2017ACM校赛 C组合数 D递推式 E折半枚举 K思维
- POST和Get的区别
- 【hackerrank】World CodeSprint 11 T4
- iOS CoreAnimation(一)图层与视图,寄宿图
- 01Groovy简介
- 【详解】平面中最接近点对问题
- 如何处理训练样本不均衡的问题
- 【WEEX,MAC踩坑】Environment variable $ANDROID_HOME not found
- Eclipse安装Spring插件
- 【hackerrank】World CodeSprint 11 T6
- C语言程序设计(35)
- 形态学处理
- CIL之——值类型与引用类型的声明和使用
- 之江学院 K: qwb与小数(思维求A/B第n位小数)