题目链接:P1141 01迷宫
程序说明:
可以用bfs来做,但是数据毒瘤,如果每次询问都运行一次bfs,会有三个TLE。。可以将路途经过的点储存起来并且记录答案,如果询问的点已经被记录了答案,直接输出答案就行了,这里是用一个队列存经过的点。d数组用于标记是否能走到,注意每次bfs不需要更新d数组。
另外参考了大佬们的题解,发现用dfs会更简单。近似于找连通块并染色(不同的连通块用不同的 i 赋值)。
代码如下:
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1010;
struct point {
int x, y;
};
char g[N][N];
int n, m, d[N][N], cnt, res[N][N];
int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
void bfs(int x, int y) {
queue<point> q;
//把经过的点放入que队列
queue<point> que;
//memset(d, -1, sizeof d);
point p;
p.x = x, p.y = y;
d[p.x][p.y] = 1;
q.push(p);
while(!q.empty()) {
point p1 = q.front();
que.push(p1);
q.pop();
for(int i = 0; i < 4; i++) {
point p2;
p2.x = p1.x + dx[i];
p2.y = p1.y + dy[i];
if(p2.x > 0 && p2.y > 0 && p2.x <= n && p2.y <= n
&& d[p2.x][p2.y] == -1 && g[p2.x][p2.y] != g[p1.x][p1.y]) {
d[p2.x][p2.y] = 1;
cnt++;
q.push(p2);
}
}
}
//将经过的点全部记录答案
while(!que.empty()) {
point p3 = que.front();
res[p3.x][p3.y] = cnt;
que.pop();
}
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0) ;
cin>>n>>m;
memset(d, -1, sizeof d);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
cin>>g[i][j];
while(m--) {
int x, y;
cin>>x>>y;
if(d[x][y] != -1) cout<<res[x][y]<<endl;
else {
cnt = 1;
bfs(x, y);
cout<<res[x][y]<<endl;
}
}
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1010, M = 100010;
char g[N][N];
int n, m, d[N][N], cnt, res[M];
int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
void dfs(int x, int y, int z, int i) {
if(x <= 0 || y <= 0 || x > n || y > n
|| d[x][y] != -1 || z != g[x][y] - '0') return;
d[x][y] = i; //连通块染色
res[i]++;
for(int j = 0; j < 4; j++) {
int x1 = x + dx[j];
int y1 = y + dy[j];
dfs(x1, y1, !z, i);
}
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0) ;
cin>>n>>m;
memset(d, -1, sizeof d);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
cin>>g[i][j];
for(int i = 1; i <= m; i++) {
int x, y;
cin>>x>>y;
if(d[x][y] == -1)
dfs(x, y, g[x][y] - '0', i);
else
res[i] = res[d[x][y]];
}
for(int i = 1; i <= m; i++)
cout<<res[i]<<endl;
return 0;
}