大概翻译一下题意:
在与联邦的战争接连失败之后,帝国方面撤退到了最后的据点。凭借着强大的防御系统,帝国军击退了联邦的六波进攻。经过几天不眠不休的思考,Arthur,联邦统帅,注意到防御系统的唯一弱点是它的能源供应。该系统由n个核电站进行充电,任何一个核电站的故障都会导致系统失效。
将军很快就发动了一次突袭,突袭者是准备潜行进入要塞的N名特工。不幸的是,由于帝国空军的攻击,他们未能按预期的位置着陆。作为一名经验丰富的将军,Arthur很快意识到他需要重新安排计划。他现在想知道的第一件事是哪个特工离任何一个发电站最近。大副,你能帮解决将军这个问题吗?
其实就是求最近点对,只不过两个点必须处于不同的集合,用分治乱搞一下就过了。
代码实现如下:
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (register int i = a; i <= b; i++) const int inf = 0x3f3f3f3f, maxn = 1e5 + 5; int T, n; double ans; struct node { int x, y, id; }p[maxn], q[maxn]; int cmp_x(node a, node b) {return a.x < b.x;} int cmp_y(node a, node b) {return a.y < b.y;} int ABS(int a, int b) {return a > b ? a - b : b - a;} double MIN(double a, double b) {return a < b ? a : b;} int read() { int x = 0, flag = 0; char ch = ‘ ‘; while (ch != ‘-‘ && (ch < ‘0‘ || ch > ‘9‘)) ch = getchar(); if (ch == ‘-‘) { flag = 1; ch = getchar(); } while (ch >= ‘0‘ && ch <= ‘9‘) { x = (x << 1) + (x << 3) + ch - ‘0‘; ch = getchar(); } return flag ? -x : x; } double dis(node a, node b) { if (a.id == b.id) return inf; return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } double divide(int l, int r) { if (l == r) return inf; int cnt = 0, mid = (l + r) >> 1; double ans = MIN(divide(l, mid), divide(mid + 1, r)); rep(i, l, r) { if (ABS(p[i].x, p[mid].x) > ans) break; else q[++cnt] = p[i]; } sort(q + 1, q + cnt + 1, cmp_y); rep(i, 1, cnt) rep(j, 1, cnt) { if (ABS(q[i].y, q[j].y) > ans) break;//复制粘贴时忘了把mid改成j,快调吐血了才发现这个傻逼错误. else ans = MIN(ans, dis(q[i], q[j])); } return ans; } int main() { T = read(); while (T--) { n = read(); rep(i, 1, n << 1) { p[i].x = read(), p[i].y = read(); if (i <= n) p[i].id = 0; else p[i].id = 1; } sort(p + 1, p + (n << 1) + 1, cmp_x); ans = divide(1, n << 1); printf("%.3f\n", ans); } return 0; }
原文地址:https://www.cnblogs.com/Kirisame-Marisa/p/10843722.html
时间: 2024-11-05 20:42:04