H.YXY的迷宫
时间限制: C/C++ 10000ms; Java 20000ms 内存限制: 65535KB
通过次数: 11 总提交次数: 28
问题描述
YXY给出了一个仅由数字0与1组成的n*n的迷宫,你可以站在这个迷宫的某一格上,若你当前所处位置为数字0,那么你可以移动到相邻4个方向(上下左右)上数字为1的格子上。同样若你当前所处位置为数字1,那么你可以移动到相邻4个方向上数字为0的格子上。对于迷宫的一个格子,询问由这一格可以到达的格子的总数是多少(包括自身的初始位置)。
输入描述
第一行输入两个正整数n和m。n表示将要输入的迷宫为n*n,m表示共有m次询问。(保证1<=n<=1000,1<=m<=100000)
接下来输入n行,每行输入n个字符。(输入保证字符均为为0或1,字符之间没有空格)
接下来输入m行,每行输入两个正整数i,j。表示询问从第i行第j列这个格子出发,一共能够到达格子的总数。
输出描述
输出共m行,每行输出一个数表示对应询问的答案。
样例输入
2 2 01 10 1 1 2 2
样例输出
4 4
来源
中北大学2018年新生赛
提示
样例解释:
对于
01
10
这个迷宫
左上角的0(第1行第1列)可以首先可以到达两个1(第1行第2列)(第2行第1列)的位置,然后这两个1又都可以到达两个0(第1行第1列)(第2行第2列)的位置。
所以从(1,1)出发,可以到达的格子总数为4
新生赛的一道题目,下来发现这个题是真的简单,真的水,当时想的是遍历每个格子,求每个格子联通块的数量,又不知道怎么标记,看了题解,我真的发自内心的嘲笑自己。
用一个数组标记每个是否走过,这个点处于哪个连通块,很简单的dfs,附上代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1010;
int ans[100100];
char maze[maxn][maxn];
int n,m,cnt,lay=1;
int vis[maxn][maxn],visit[100100];
int dir[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};
void dfs(int x, int y, int cur)
{
vis[x][y] = lay;
visit[lay] = ++cnt;
for (int i = 0; i < 4; ++i)
{
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if (xx < 0 || xx >= n || yy < 0 || yy >= n || vis[xx][yy] == lay)
continue;
int next = maze[xx][yy] - '0';
if (next == !cur)
{
dfs(xx, yy, next);
}
}
}
int main()
{
memset(visit,-1,sizeof(visit));
int top=0;
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
scanf("%s",maze[i]);
for(int i=0; i<m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(visit[vis[x-1][y-1]]==-1)
{
dfs(x-1,y-1,maze[x-1][y-1]-'0');
ans[top++]=visit[vis[x-1][y-1]];
}
else
{
ans[top++]=visit[vis[x-1][y-1]];
}
cnt=0;
lay++;
printf("%d\n",ans[i]);
}
}