NC232262. 公平公正的风行迷踪
描述
我们可以把风行迷踪的地图简化为一个坐标系下的正方形,正方形的四个顶点分别是 ,我们以上帝视角可以得知所有游侠的位置 ,猎手和游侠都只能在正方形内进行探索或躲藏。由于所有游侠都被施加了禁锢诅咒,并且猎手暂停了时间,所以所有的游侠都可以看作是一个个隐藏的点。现在,猎手的感应光环技能的探索半径为 (即猎手可以发现一名与她距离小于等于 的游侠)。猎手将从原点 出发,向 轴正方向开始进行探索,如果她在原点或前进过程中使用感应光环发现了游侠,她将改变方向朝着游侠前进,直到捕获游侠(此过程中,猎手不会使用感应光环),如果她在捕获了一个游侠后又通过感应光环发现了另一个游侠,那么她将向着下一个游侠的位置前进,否则她将不改变方向继续前进。若她到了正方形的边界或边角无法再前进时,她将沿着边界逆时针绕行。
注意:在某一时刻,如果有多名游侠同时出现在感应光环的范围内,根据左手定则,猎手将只发现位置在正方形最左下角的游侠(最左下的定义为优先最左其次最下)。
那么,嘤嘤想知道她能捕获多少名游侠?(一个游侠被捕获后,游侠将立刻从地图上消失)
输入描述
第一行两个整数 , , 表示游侠数量, 表示感应光环的半径。
接下来 行,每行两个整数 , ,表示游侠的位置 。
题目保证不会有位置相同的游侠,且原点没有游侠。
输出描述
一个整数,表示旅行者能捕获的游侠数。并按捕获顺序输出游侠的编号。
示例1
输入:
4 2 3 3 9 2 9 9 12 12
输出:
2 2 3
示例2
输入:
3 6 2 2 15 7 13 13
输出:
2 1 3
C++ 解法, 执行用时: 48ms, 内存消耗: 604K, 提交时间: 2022-01-01 00:42:36
#include <bits/stdc++.h> int main() { using namespace std; using LD = long double; using LL = long long; constexpr LD eps = 1e-10; struct P { LD x, y; LD dis(const P& p) const { return hypot(x - p.x, y - p.y); } LD dot(const P& p) const { return x * p.x + y * p.y; } P norm() const { LD d = hypot(x, y); return {x / d, y / d}; } P r90() const { return {-y, x}; } P operator + (const P& p) const { return {x + p.x, y + p.y}; } P operator - (const P& p) const { return {x - p.x, y - p.y}; } P operator * (LD k) const { return {x * k, y * k}; } }; ios::sync_with_stdio(false); cin.tie(nullptr); int n; LD r; cin >> n >> r; vector<P> p(n); vector<int> cd(n), ans; for (auto& [x, y] : p) cin >> x >> y; P cur = {0, 0}, dir = {1, 0}; int ch = 0; while (ch < 8) { //cout << cur.x << " " << cur.y << " " << dir.x << " " << dir.y << "\n"; int s = -1; LD mt = -1; auto f = [](LD cur, LD dir) { if (abs(dir) < eps) return (LD)1E100; if (dir < 0) return cur / -dir; return (1000000 - cur) / dir; }; LD xt = f(cur.x, dir.x), yt = f(cur.y, dir.y); auto update = [&](int i, double t) { if (t > xt + eps or t > yt + eps) return; if (s == -1) { s = i; mt = t; } if (mt > t) { s = i; mt = t; } if (mt == t and p[i].x < p[s].x) { s = i; mt = t; } if (mt == t and p[i].x == p[s].x and p[i].y < p[s].y) { s = i; mt = t; } }; for (int i = 0; i < n; i += 1) if (not cd[i]) { if (cur.dis(p[i]) <= r + eps) update(i, 0); else { LD x = (p[i] - cur).dot(dir.r90()); LD y = (p[i] - cur).dot(dir); if (y >= eps and abs(x) <= r + eps) update(i, y - sqrt(max(r * r - x * x, LD(0)))); } } if (s != -1) { cd[s] = 1; ans.push_back(s); dir = (p[s] - (cur + dir * mt)).norm(); cur = p[s]; ch = 0; } else { LD xt = f(cur.x, dir.x), yt = f(cur.y, dir.y); if (abs(xt - yt) < eps) { cur = cur + dir * xt; if (dir.x > 0 and dir.y > 0) dir = {-1, 0}; else if (dir.x < 0 and dir.y > 0) dir = {0, -1}; else if (dir.x < 0 and dir.y < 0) dir = {1, 0}; else dir = {0, 1}; } else if (xt < yt) { cur = cur + dir * xt; if (dir.x > 0) dir = {0, 1}; else dir = {0, -1}; } else { cur = cur + dir * yt; if (dir.y > 0) dir = {-1, 0}; else dir = {1, 0}; } ch += 1; } } cout << ans.size() << '\n'; for (int x : ans) cout << x + 1 << " "; return 0; }