比赛链接:
https://codeforces.com/contest/1651
D. Nearest Excluded Points
题目大意:
在平面上有 \(n\) 个不同的点,这些点在一个集合中,输出离集合中每一个点最近的不在集合中的点,距离以曼哈顿距离计算。
思路:
先从集合中的点中找出周围(上下左右)有不在集合中的点,可以将这些点理解为在集合的边缘的点,离这些点最近的不在集合中的点就是它们周围的一个点。
然后以这些点展开搜索,通过 \(bfs\),逐步向内部推进,更新集合中的点,直到更新完全部点。可以用 \(map\) 储存每一个点最近的那个点。
代码:
#include <bits/stdc++.h>
using namespace std;
#define IOS() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fi first
#define se second
#define pii pair<int, int>
#define all(x) (x).begin(), (x).end()
int n, dx[] = {-1, 0, 1, 0}, dy[] = {0, -1, 0, 1};
int main(){
IOS();
cin >> n;
vector <pii> p(n);
for (int i = 0; i < n; ++ i)
cin >> p[i].fi >> p[i].se;
queue <pii> q;
map <pii, pii> ans;
set <pii> s(all(p));
for (int i = 0; i < n; ++ i){
int x = p[i].fi, y = p[i].se;
for (int j = 0; j < 4; ++ j){
int nx = x + dx[j], ny = y + dy[j];
if (s.count({nx, ny})) continue;
q.push({x, y});
ans[{x, y}] = {nx, ny};
break;
}
}
while (q.size()){
pii nd = q.front();
q.pop();
int x = nd.fi, y = nd.se;
for (int i = 0; i < 4; ++ i){
int nx = x + dx[i], ny = y + dy[i];
if (!s.count({nx, ny}) || ans.count({nx, ny})) continue;
ans[{nx, ny}] = ans[{x, y}];
q.push({nx, ny});
}
}
for (auto &x : p){
auto t = ans[x];
cout << t.fi << " " << t.se << "\n";
}
return 0;
}