洛谷P1141 01迷宫 (BFS连通块问题)
题目链接
P1141 01迷宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
类似的题目
思路
像之前那样写BFS的话会有三个点tle
需要优化。
这里可推出,在一个位置去查找路径时,路径上所有的格子的答案都是一样的。
以样例为例,这张图上所有数字都是连通的,即不管找哪个位置的数都是答案都是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就行。