洛谷P1141 01迷宫

题目描述

有一个仅由数字0与11组成的n×n格迷宫。若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上。

你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。


输入格式:

第1行为两个正整数n,m。

下面n行,每行n个字符,字符只可能是0或者1,字符之间没有空格。

接下来mm行,每行2个用空格分隔的正整数i,j,对应了迷宫中第i行第j列的一个格子,询问从这一格开始能移动到多少格。

输出格式:

输入样例#1:

2 2

01
10
1 1
2 2
输出样例#1:
4
4

说明


所有格子互相可达。

对于20%的数据,n≤10n≤10;

对于40%的数据,n≤50n≤50;

对于50%的数据,m≤5m≤5;

对于60%的数据,n≤100,m≤100n≤100,m≤100;

对于100%的数据,n≤1000,m≤100000n≤1000,m≤100000。

题目分析

很普通的bfs题,但是注意到她的数据规模很大,要适当的优化。

分析题过后,我们可以发现,迷宫当中可以互相到达的点,能够组成一个集合,且集合中的点能移动几个格子的个数都是相等的,

另外,在输入矩阵时,数字之间没有空格,我们需要用scanf(“%1d”, &maze[i][j])来读取。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
using namespace std;
struct node {
	int x, y;
	node(int a, int b) {
		x = a;
		y = b;
	}
};
int n, m;
int maze[1000 + 2][1000 + 2];
int dir[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
int p_sum[1000 + 2][1000 + 2];//标记第i行j列的点,在哪个集合中
int set[100000 + 2];//第i个集合中的点能走几步
bool check(int x, int y) {
	if (x < 0 || y < 0 || y >= n || x >= n)
		return false;
	return true;
}
int bfs(int index,int a, int b) {
	int sum = 0;
	queue<node> myq;
	myq.push(node(a, b));
	while (!myq.empty()) {
		//出队
		int x = myq.front().x;
		int y = myq.front().y;
		myq.pop();
		//若已在集合中,则跳过
		if (p_sum[x][y] != 0)
			continue;
		//将点加入集合
		p_sum[x][y] = index;
		sum++;
		//枚举所有方向
		for (int i = 0; i < 4; i++) {
			int xx = x + dir[i][0];
			int yy = y + dir[i][1];
			if (check(xx, yy) && maze[x][y] != maze[xx][yy])
				myq.push(node(xx, yy));
		}
	}
	set[index] = sum;
	return sum;
}
int main(){
	scanf("%d %d\n", &n, &m);
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			scanf("%1d", &maze[i][j]);
		}
	}
	for (int i = 0; i < m; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		if (p_sum[a - 1][b - 1])
			cout << set[p_sum[a - 1][b - 1]] << endl;
		else
			cout << bfs(i + 1, a - 1, b - 1) << endl;
	}
	return 0;
}
posted @ 2019-04-04 12:59  阳离子  阅读(247)  评论(0编辑  收藏  举报