1 条题解
-
0
自动搬运
来自洛谷,原作者为

hs_black
Go for broke搬运于
2025-08-24 22:21:26,当前版本为作者最后更新于2020-07-05 22:46:24,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P6505 Run Away
题解区给出的都是 Voronoi 图的神仙做法,但这里将介绍一种很玄学但很好写又很快的做法
首先看到最远距离,先进行二分这个距离,这是所有的点扩散成一个个圆,我们只需要判断这些圆是否完全填满了这个矩形,那么如何判断呢
那么很玄学的就来了,我们采用分治的思想,首先一个矩形,先判断它是否可以只被一个圆覆盖,然后判断四个角只要有一个角没被覆盖就不行,如果都被覆盖了,那么递归下去,将大矩形横竖切两刀分成四个小矩形继续判断,当矩形的长度小于精度要求时返回 false
这个看起来很玄学,但实际跑起来飞快,缺点是速度和精度有关,请谨慎使用
代码部分借鉴 Luitaryi
#pragma GCC optimize(3, "inline") #include <iostream> #include <cstdio> #define R register int using namespace std; inline int g() { R x = 0, f = 1; register char s; while (!isdigit(s = getchar())) f = s == '-' ? -1 : f; do x = x * 10 + (s ^ 48); while (isdigit(s = getchar())); return x * f; } const double E = 1e-7; const int N = 50001; int n, L, W, a[N], b[N]; double c, d[N]; inline bool in(double x, double y, int i) { return (x - a[i]) * (x - a[i]) + (y - b[i]) * (y - b[i]) <= c; } inline bool ck(double x, double y, double l, double w) { if (l < E && w < E) return false; for (R i = 1; i <= n; ++i) if (in(x, y, i) && in(x + l, y, i) && in(x, y + w, i) && in(x + l, y + w, i)) return true; register double L = l / 2, W = w / 2; return ck(x, y, L, W) && ck(x + L, y, L, W) && ck(x, y + W, L, W) && ck(x + L, y + W, L, W); } signed main() { L = g(), W = g(), n = g(); for (R i = 1; i <= n; ++i) a[i] = g(), b[i] = g(); register double l = 0, r = 20000, md; while (r - l > 1e-6) { md = (l + r) / 2; c = md * md; if (ck(0, 0, L, W)) r = md; else l = md; } printf("%.6f\n", l); return 0; }
- 1
信息
- ID
- 5545
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者