题目链接:https://www.luogu.org/problemnew/show/P1141
题意:给一个n*n
的仅由01
构成的迷宫,输出从某一点出发所能走到的最多格子,如果所处方块是0,则可以走到四个方向上的1去,反之亦然。
思路:
1.如果这一格的步数已经大于0就直接输出,否则dfs,并标记,具体的看代码。
2.另外所谓的走格子规则,其实就是周围四个方向的格子跟所在的格子不等就行。
3.其实就是求出图中的联通块,我们把一个联通块看成一个房间。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int n,m;
int map[1005][1005];
int vis[1005][1005];
int roomarea=0;//这名字很好理解吧
int pa[1000001][2];//临时数组,用来存放同一个房间的x,y坐标,以便于全部赋值为该房间的格子数,因为dfs过程中是不知道这个联通块的格子数目的。而且要开大点,不然第9个点会RE
int dx[4]={0,0,1,-1};//方向数组
int dy[4]={1,-1,0,0};
void dfs(int x,int y){
roomarea++;//格子数++
pa[roomarea][0]=x;//存临时坐标
pa[roomarea][1]=y;
vis[x][y]=1;//标记为访问过
for(int i=0;i<4;i++){
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<1||yy<1||xx>n||yy>n)//出界了不行
continue;
if(vis[xx][yy])//访问过的不行
continue;
if(map[xx][yy]==map[x][y])相等的不行
continue;
dfs(xx,yy);
}
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%1d",&map[i][j]);//读入
}
}
memset(vis,0,sizeof(vis));//即是标记,也是储存一个房间内格子数目
for(int i=1;i<=m;i++){
int p1,p2;
scanf("%d %d",&p1,&p2);//读入起始坐标
roomarea=0;//格子数赋0
if(vis[p1][p2]>0){//如果大于0,就直接输出了
printf("%d\n",vis[p1][p2]);
continue;
}
dfs(p1,p2);//从这个点开始dfs
for(int j=1;j<=roomarea;j++){
vis[pa[j][0]][pa[j][1]]=roomarea;//将这个房间的所有格子赋为该房间的格子数,以方便以后直接输出
}
printf("%d\n",roomarea);
}
return 0;
}
总结:dfs求联通块,外加一点统计技巧。