新千题计划 1#:[NOIP10 普及] 导弹拦截

导弹拦截 平面内两导弹拦截系统,位置固定,各可拦截以其位置为圆心之一圆形区域,但半径可调整。今拦截 N 个坐标已知之导弹,求两拦截半径平方和之最小值.

模拟。一道普及题百思不得,题解见证我的无知。

系统甲必有一拦截范围。其内部点由甲拦截,故甲之范围为此点至甲距离最大值;外部由乙拦截同理。故必有一点为两者分界,至甲距离 <= 此则归甲,否则归乙。

故我们以至甲距离为关键字排序,对各点 id1[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);
}

猜你喜欢

转载自blog.csdn.net/qq_19982679/article/details/81437759