要点
- 题意:可以拐弯,即哈密顿距离
- 注意不可以直接一个一个搜,这过程中会把下一轮的标记上,导致同一轮的其它点没能正常完成应有的搜索
- 因此采用双层广搜,把同一轮先都出队列再的一起搜
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cctype>
using namespace std;
const int maxp = 10;
const int tx[] = {0, 0, -1, 1};
const int ty[] = {-1, 1, 0, 0};
struct node {
int x, y, c;
node() {}
node(int a, int b, int c):x(a), y(b), c(c) {}
};
int n, m, p;
int pace[maxp];
char grid[1001][1001];
vector<node> st[maxp];
queue<node> Q;
queue<pair<node, int>> q;
int cnt[maxp];
int main() {
scanf("%d %d %d", &n, &m, &p);
for (int i = 1; i <= p; i++)
scanf("%d", &pace[i]);
for (int i = 1; i <= n; i++) {
scanf("%s", grid[i] + 1);
for (int j = 1; j <= m; j++)
if (isdigit(grid[i][j]))
st[grid[i][j] - '0'].emplace_back(i, j, grid[i][j] - '0');
}
for (int i = 1; i <= p; i++)
for (auto j : st[i])
Q.emplace(j);
while (!Q.empty()) {
auto t = Q.front(); Q.pop();
for (int dir = 0; dir < 4; dir++) {//本轮第一步
int nx = t.x + tx[dir], ny = t.y + ty[dir];
if (nx < 1 || nx > n || ny < 1 || ny > m || grid[nx][ny] != '.') continue;
grid[nx][ny] = t.c + '0';
q.emplace((node){nx, ny, t.c}, 1);
}
if (Q.size() && t.c == Q.front().c) continue;//同一轮的所有人一起扩展
while (!q.empty()) {//本轮扩展
node tmp = q.front().first;
int len = q.front().second;
q.pop();
if (len == pace[tmp.c]) {//本次最外界
Q.emplace(tmp); continue;
}
for (int dir = 0; dir < 4; dir++) {
int nx = tmp.x + tx[dir], ny = tmp.y + ty[dir];
if (nx < 1 || nx > n || ny < 1 || ny > m || grid[nx][ny] != '.') continue;
grid[nx][ny] = tmp.c + '0';
q.emplace((node){nx, ny, tmp.c}, len + 1);
}
}
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (isdigit(grid[i][j]))
cnt[grid[i][j] - '0']++;
for (int i = 1; i <= p; i++)
printf("%d ", cnt[i]);
}