赞
踩
在真空中,一块无限平坦光滑绝缘不导热草地上有很多光滑且相同球形竹鼠,它们的坐标为(xi,yi)。竹鼠之间会通过脑电波联系彼此。现在请问相距最近两只竹鼠的直线距离分别是多少(所有竹鼠都在草地的第一象限)?
输入格式:
第一行一个整数n;
接下来 n行每行两个非负浮点数,xi,yi,表示第 i个点的 X 坐标与 Y 坐标。xi,yi都精确到小数点后两位。
输出格式:
一行,一个浮点数,最短距离。精确到小数点后4位。
输入:
4 0.0 0.0 0.0 1.0 1.0 0.0 1.0 1.0
输出:
1.0000
其中: 0≤n≤10^5,竹鼠的坐标数据范围在int型范围内。并且可能会有重叠的竹鼠。
思路:模板题,最近点对问题,用分治解决。
即将区域分成 l----mid---r,即最短距离有三种情况:全在左边、全在右边、一个在左一个在右
- #include <bits/stdc++.h>
- using namespace std;
- #define INF 10000000001
- const int N = 1e5 + 7;
- struct node
- {
- double x, y;
- } a[N];
- int n, t[N];
- double ans = 0;
- bool cmp(node &a, node &b)//x,y升序
- {
- if (a.x < b.x)
- return true;
- else if (a.x == b.x && a.y < b.y)
- return true;
- else
- return false;
- }
- bool cmp2(int &i, int &j)
- {
- if (a[i].y < a[j].y) // 按y升序
- return true;
- else
- return false;
- }
- double dis(int i, int j)
- {
- double c = sqrt((a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) * (a[i].y - a[j].y));
- return c;
- }
- double merge(int l, int r)
- {
- if (l == r)//重叠
- return INF;
- if (l == r - 1)
- return dis(l, r);
- int mid = (l + r) / 2;
- double d1 = merge(l, mid);
- double d2 = merge(mid + 1, r);
- ans = min(d1, d2); // 求全在左边和全在右边的最小值
- int k = 0;
- // 求一左一右的最小值
- for (int i = l; i <= r; i++)
- {
- if (fabs(a[i].x - a[mid].x) <= ans) // 将一左一右的编号写入t
- {
- t[k] = i;
- k++;
- }
- sort(t, t + k, cmp2);
- for (int i = 0; i < k; i++)
- {
- for (int j = i + 1; j < k && a[t[j]].y - a[t[i]].y < ans; j++)
- {
- ans = min(ans, dis(t[i], t[j]));
- }
- }
- }
- return ans;
- }
- int main()
- {
- cin >> n;
- for (int i = 0; i < n; i++)
- cin >> a[i].x >> a[i].y;
- sort(a, a + n, cmp);
- printf("%.4f", merge(0, n - 1));
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。