Codeforces 1105D(双层广搜)

要点

  • 题意:可以拐弯,即哈密顿距离
  • 注意不可以直接一个一个搜,这过程中会把下一轮的标记上,导致同一轮的其它点没能正常完成应有的搜索
  • 因此采用双层广搜,把同一轮先都出队列再的一起搜
#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]);
}
原文地址:https://www.cnblogs.com/AlphaWA/p/11001836.html