导弹拦截 平面内两导弹拦截系统,位置固定,各可拦截以其位置为圆心之一圆形区域,但半径可调整。今拦截 个坐标已知之导弹,求两拦截半径平方和之最小值.
模拟。一道普及题百思不得,题解见证我的无知。
系统甲必有一拦截范围。其内部点由甲拦截,故甲之范围为此点至甲距离最大值;外部由乙拦截同理。故必有一点为两者分界,至甲距离 <=
此则归甲,否则归乙。
故我们以至甲距离为关键字排序,对各点 i
, d1[i]
为 [1..i]
至甲距离平方之最大值, d2[i]
为 [i..n]
至乙距离平方之最大值,若以 i
分界,则平方和为 d1[i] + d2[i + 1]
,故最终答案为 min{d1[i] + d2[i + 1]}
.
#include <cstdio>
#include <cstdlib>
#include <utility>
#include <algorithm>
typedef std::pair<int, int> BINT;
const int MAXN = 100001;
int n, d1[MAXN], d2[MAXN], ans = 0x7fffffff; BINT p1, p2, p[MAXN];
inline int Dst(BINT u, BINT v) {
int dx = abs(u.first - v.first), dy = abs(u.second - v.second);
return dx * dx + dy * dy;
}
int main() {
scanf("%d%d%d%d%d", &p1.first, &p1.second, &p2.first, &p2.second, &n);
for(int i = 0; i < n; i++) scanf("%d%d", &p[i].first, &p[i].second);
std::sort(p, p + n, [](BINT u, BINT v) { return Dst(u, p1) < Dst(v, p1); });
for(int i = 0; i < n; i++) d1[i] = std::max(d1[i - 1], Dst(p[i], p1));
for(int i = n - 1; ~i; i--) d2[i] = std::max(d2[i + 1], Dst(p[i], p2));
for(int i = 0; i < n; i++) ans = std::min(ans, d1[i] + d2[i + 1]);
return !printf("%d\n", ans);
}