洛谷P1141 01迷宫 (BFS连通块问题)

题目链接

P1141 01迷宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

类似的题目

思路

像之前那样写BFS的话会有三个点tle
image

需要优化。

这里可推出,在一个位置去查找路径时,路径上所有的格子的答案都是一样的。
image
以样例为例,这张图上所有数字都是连通的,即不管找哪个位置的数都是答案都是4

更复杂的例子就不举了(懒得画)

那么只要算出一个答案,再把它路过的所有点也一起标记成这个答案即可,(也称染色)

这样算出一个点的答案同时求出了好几个点的最终答案。

AC代码

#include <iostream>
#include <queue>
using namespace std;
int n, m;
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };//算方向的数组
int a[1005][1005];//地图数组
bool visited[1005][1005];//标记是否去过的同时记录这个位置是否已经在之前被算过了
pair<int,int> s[1000001];//记录经过路径的数组
int step[1005][1005];//记录最终答案的数组
void bfs(int x, int y)
{
	int ans = 1;
	queue<pair<int, int>>q;
	pair<int, int> temp = { x,y };
	q.push(temp);//经典BFS三板斧第一式
	visited[x][y] = 1;
	s[ans] = { x,y };//把自己送入经过路径的数组
	while (!q.empty())
	{
		auto t = q.front();
		q.pop();
		for (int c = 0; c < 4; c++)
		{
			int new_x = t.first + dx[c];
			int new_y = t.second + dy[c];
			if (new_x >= 1 && new_x <= n && new_y >= 1 && new_y <= n && a[t.first][t.second] != a[new_x][new_y] && !visited[new_x][new_y])
			{//如果下一个点可去
				{
					pair<int, int>temp = { new_x,new_y };
					q.push(temp);
					ans++;
					s[ans] = { new_x,new_y };//把经过路径压入数组
					visited[new_x][new_y] = 1;
				}
			}
		}
	}
	for (int i = 1; i <= ans; i++)
	{
		step[s[i].first][s[i].second] = ans;//染色,把所有经过的路径标记为相同的答案
	}
}
int main(int argc, char* argv[])
{
	cin >> n >> m;

	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			char t;
			cin >> t;
			if (t == '\n')
				cin >> t;
			a[i][j] = t - '0';
		}
	}
	for (int i = 0; i < m; i++)
	{
		int t1, t2;
		cin >> t1 >> t2;
		if (!visited[t1][t2])
			bfs(t1, t2);//如果这点没有经过才进行搜索
		cout << step[t1][t2] << endl;//否则直接输出答案,在大量数据时省去很多时间,避免TLE
	}
	return 0;

}

心得:本来以为是简单题,结果被干碎了。洛谷的字符输入用getchar()和scanf好像都有问题,用cin就行。

image

posted @ 2022-01-13 23:03  张牧歌  阅读(237)  评论(1编辑  收藏  举报