编辑
2024-09-25
算法题
00
请注意,本文编写于 226 天前,最后修改于 226 天前,其中某些信息可能已经过时。

目录

01迷宫
题目描述
输入格式
输出格式
样例 #1
样例输入 #1
样例输出 #1
提示

https://www.luogu.com.cn/problem/P1141

01迷宫

题目描述

有一个仅由数字 0011 组成的 n×nn \times n 格迷宫。若你位于一格 00 上,那么你可以移动到相邻 44 格中的某一格 11 上,同样若你位于一格 11 上,那么你可以移动到相邻 44 格中的某一格 00 上。 你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。

输入格式

第一行为两个正整数 n,mn,m。 下面 nn 行,每行 nn 个字符,字符只可能是 00 或者 11,字符之间没有空格。 接下来 mm 行,每行两个用空格分隔的正整数 i,ji,j,对应了迷宫中第 ii 行第 jj 列的一个格子,询问从这一格开始能移动到多少格。

输出格式

mm 行,对于每个询问输出相应答案。

样例 #1

样例输入 #1

2 2 01 10 1 1 2 2

样例输出 #1

4 4

提示

对于样例,所有格子互相可达。

  • 对于 20%20\% 的数据,n10n \leq 10
  • 对于 40%40\% 的数据,n50n \leq 50
  • 对于 50%50\% 的数据,m5m \leq 5
  • 对于 60%60\% 的数据,n,m100n,m \leq 100
  • 对于 100%100\% 的数据,1n10001\le n \leq 10001m1000001\le m \leq 100000

这题其实就是计算在这个图里某个点所处的连通块大小,很明显的是

所有在同一个连通块的点大小一样,所以不用重复求,跳过就可以

简单的韵做法是bfs的时候给每个连通块编号。代码如下

cpp
#include <iostream> #include <queue> #include <cstring> using namespace std; const int MAXN = 1005; int n, m; char maze[MAXN][MAXN]; int component[MAXN][MAXN]; int componentSize[MAXN * MAXN]; int dx[] = {0, 0, 1, -1}; int dy[] = {1, -1, 0, 0}; void bfs(int x, int y, int compId) { queue<pair<int, int>> q; q.push({x, y}); component[x][y] = compId; int size = 0; while (!q.empty()) { auto [cx, cy] = q.front(); q.pop(); size++; for (int i = 0; i < 4; i++) { int nx = cx + dx[i]; int ny = cy + dy[i]; if (nx >= 0 && nx < n && ny >= 0 && ny < n && component[nx][ny] == -1 && maze[nx][ny] != maze[cx][cy]) { component[nx][ny] = compId; q.push({nx, ny}); } } } componentSize[compId] = size; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m; for (int i = 0; i < n; i++) { cin >> maze[i]; } memset(component, -1, sizeof(component)); int compId = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (component[i][j] == -1) { bfs(i, j, compId++); } } } while (m--) { int x, y; cin >> x >> y; x--; y--; cout << componentSize[component[x][y]] << '\n'; } return 0; }

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!