P1141 01迷宫
6.4K
通过
32.7K
提交
题目提供者
评测方式 云端评测
标签 高性能
难度 普及/提高-
时空限制 1000ms / 128MB
提示:收藏到任务计划后,可在首页查看。
最新讨论
推荐的相关题目
题目描述
有一个仅由数字00与11组成的n \times nn×n格迷宫。若你位于一格0上,那么你可以移动到相邻44格中的某一格11上,同样若你位于一格1上,那么你可以移动到相邻44格中的某一格00上。
你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。
输入输出格式
输入格式:
第11行为两个正整数n,mn,m。
下面nn行,每行nn个字符,字符只可能是00或者11,字符之间没有空格。
接下来mm行,每行22个用空格分隔的正整数i,ji,j,对应了迷宫中第ii行第jj列的一个格子,询问从这一格开始能移动到多少格。
输出格式:
mm行,对于每个询问输出相应答案。
输入输出样例
输入样例#1:
2 2
01
10
1 1
2 2
输出样例#1:
4
4
说明
所有格子互相可达。
对于20\%20%的数据,n≤10n≤10;
对于40\%40%的数据,n≤50n≤50;
对于50\%50%的数据,m≤5m≤5;
对于60\%60%的数据,n≤100,m≤100n≤100,m≤100;
对于100\%100%的数据,n≤1000,m≤100000n≤1000,m≤100000。
刚开始直接对需要查询的点进行BFS,结果得了70分,有三个样例TLE了。
于是开始改进,我们想到:在同一个联通块内的答案是一样的,好,知道了
这一点就很简单了。我们再开一个栈/队列记录下来以
(i,j)
(
i
,
j
)
为起点的联通块
路径,记忆化即可。然后我们只需要
BFS
B
F
S
那些还没有答案的即可。
PS:
P
S
:
栈和队列的定义最好在外面,否则可能会TLE,因为每次变量的重新
声明都需要时间。
#include<bits/stdc++.h>
using namespace std;
const int maxn =1550;
char maze[maxn][maxn];
bool vis[maxn][maxn];
int n,m;
struct node{
int x,y;
};
bool check(int x,int y){
return x>=0&&x<n&&y>=0&&y<n;
}
int dir[4][2]={-1,0,0,1,1,0,0,-1};
int num[maxn][maxn];
int ans;
node tn,rt;
stack<node> sta;
queue<node> que;
void bfs(int sx,int sy){
ans=1;
tn.x=sx;
tn.y=sy;
vis[tn.x][tn.y]=1;
que.push(tn);
while(!que.empty()){
rt=que.front();
que.pop();
for(int i=0;i<4;i++){
int dx=rt.x+dir[i][0];
int dy=rt.y+dir[i][1];
if(!vis[dx][dy]&&check(dx,dy)&&maze[dx][dy]!=maze[rt.x][rt.y]){
vis[dx][dy]=1;
tn.x=dx;
tn.y=dy;
ans++;
que.push(tn);
sta.push(tn);
}
}
}
num[sx][sy]=ans;
while(!sta.empty()){
num[sta.top().x][sta.top().y]=ans;
sta.pop();
}
}
int main(){
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++){
scanf("%s",maze[i]);
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(!vis[i][j]){
bfs(i,j);
}
}
}
int tx,ty;
while(m--){
scanf("%d %d",&tx,&ty);
printf("%d\n",num[tx-1][ty-1]);
}
return 0;
}