平面中有若干个点,寻找距离最近的两个点,输出其编号
2015-09-26 16:07
337 查看
代码:
View Code
#include <iostream> #include <vector> #include <algorithm> #include <cmath> #include <map> #include <stdio.h> using namespace std; struct Point { double m_x, m_y; Point():m_x(0.0),m_y(0.0) {} Point(double x, double y):m_x(x),m_y(y) {} bool operator==(const Point& p) const { return m_x==p.m_x && m_y==p.m_y; } }; ostream& operator<<(ostream& os, const Point& p) { return os << "(" << p.m_x << "," << p.m_y << ")"; } template<class T, class Pr> void insert_sort(vector<T> &vec, int l, int r, Pr pred) { int i, j; for (i=l+1; i<=r; i++) { T tmp = vec[i]; for (j=i-1; j>=l && pred(tmp,vec[j]); j--) vec[j+1]=vec[j]; vec[j+1] = tmp; } } template<class T> int get_position(vector<T> &vec, int l, int r, T key) { for (int i=l; i<=r; i++) if (key == vec[i]) return i; return -1; } template<class T, class Pr> int partition(vector<T> &vec, int l, int r, Pr pred) { int i, j; for (i=l+1,j=l; i<=r; i++) { if (pred(vec[i],vec[l])) { ++j; swap(vec[i],vec[j]); } } swap(vec[j],vec[l]); return j; } template<class T, class Pr> T select(vector<T> &vec, int l, int r, int k, Pr pred) { int n = r-l+1; if (n==1) { if (k!=0) printf("Out of Boundary!\n"); return vec[l]; } int cnt = n/5; int tcnt = (n+4)/5; int rem = n%5; vector<T> group(tcnt); int i, j; for (i=0,j=l; i<cnt; i++,j+=5) { insert_sort(vec, j, j+4, pred); group[i] = vec[j+2]; } if (rem) { insert_sort(vec, j, j+rem-1, pred); group[i] = vec[j+(rem-1)/2]; } T key = select(group, 0, tcnt-1, (tcnt-1)/2, pred); int key_pos = get_position(vec, l, r, key); swap(vec[key_pos], vec[l]); int pos = partition(vec, l, r, pred); int x = pos - l; if (x == k) return key; else if (x < k) return select(vec, pos+1, r, k-x-1, pred); else return select(vec, l, pos-1, k, pred); } double dist(const Point& a, const Point& b) { double x = a.m_x-b.m_x; double y = a.m_y-b.m_y; return sqrt(x*x+y*y); } bool cmpX(const Point& a, const Point& b) { return a.m_x < b.m_x; } bool cmpY(const Point& a, const Point& b) { return a.m_y < b.m_y; } double minDifferent(vector<Point> p, int l, int r, vector<Point> &result) { if ((r-l+1)==2) { result[0] = p[l]; result[1] = p[r]; if (cmpX(p[r],p[l])) swap(p[l], p[r]); return dist(p[l], p[r]); } if ((r-l+1)==3) { insert_sort(p, l, r, cmpX); double tmp1 = dist(p[l], p[l+1]); double tmp2 = dist(p[l+1], p[l+2]); double ret = min(tmp1, tmp2); if (tmp1 == ret) { result[0] = p[l]; result[1] = p[l+1]; } else { result[0] = p[l+1]; result[1] = p[l+2]; } return ret; } int mid = (r+l)>>1; Point median = select(p, l, r, mid-l, cmpX); vector<Point> res1(2), res2(2); double min_l = minDifferent(p, l, mid, res1); double min_r = minDifferent(p, mid+1, r, res2); double minum = min(min_l, min_r); if (minum == min_l) { result[0] = res1[0]; result[1] = res1[1]; } else { result[0] = res2[0]; result[1] = res2[1]; } vector<Point> yvec; int i, j; for (i=mid+1; i<=r; i++) if (p[i].m_x - p[mid].m_x < minum) yvec.push_back(Point(p[i])); for (i=mid; i>=l; i--) if (p[mid+1].m_x - p[i].m_x < minum) yvec.push_back(Point(p[i])); sort(yvec.begin(), yvec.end(), cmpY); for (i=0; i<yvec.size(); i++) { for (j=i+1; j<yvec.size() && yvec[j].m_y-yvec[i].m_y<minum && j<=i+7; j++) { double delta = dist(yvec[i],yvec[j]); if (delta < minum) { minum = delta; result[0] = yvec[i]; result[1] = yvec[j]; } } } return minum; } int main() { int n, i, j; double x, y; int k = 0; map<int,Point> m; vector<Point> result(2); vector<Point> input; cin >> n; for (i=0; i<n; i++) { cin >> x; cin >> y; input.push_back(Point(x,y)); m.insert(pair<int,Point>(k,Point(x,y))); k++; } double minum = minDifferent(input, 0, input.size()-1, result); for(map<int,Point>::iterator it = m.begin();it != m.end();it++) { if(it->second == result[0]) { cout<<it->first; } if(it->second == result[1]) { cout<<" "<<it->first; } } return 0; }
View Code
相关文章推荐
- 易Android登录Demo
- 【POJ 3269】Building A New Barn
- Android获取手机电池电量用法实例
- 常用工具总结
- 第十二篇:关于main中的两个参数的使用请况
- ListView中BaseAdapter优化三重境界
- 数组与字符串的相互转化
- PHP程序员的技术成长规划
- 微软Windows 10 IoT Core起步者套装正式发布 折合人民币713元
- 单链表
- Java Socket编程----通信是这样炼成的
- Systemd
- GraphQL Relay Specification #Facebook Relay文档翻译#
- NOI库7614 最低通行费
- 两个队列模拟一个栈
- 基于tomcat运行HTML5 WebSocket echo例子
- Java String之String和CharSequence、StringBuilder和StringBuffer的区别
- 温习c++ 基本功之标识符的作用域
- HTML 5 Web 存储
- call_user_func_array