P1141 01迷宫

· · 个人记录

这是一道 不很正经的 搜索题,个人认为这种一条一条遍历的还是 bfs 用起来舒服。

题意解读

先输入一个宽为 n 的迷宫,只由 1 和 0 组成,这让人不由自主想到用 char 来输入。然后给出 m (稍后代码用 t 代替)组 xy 。求出从这个坐标能走多少步,由题意可知,只有上下左右四周的方格与自己不同且不超出范围时才可以走。

坑点 (重点)

看上去,这道题人畜无害,就是一道普通 bfs 。但是当你看到这句话:

------------ ## 坑点处理方法 $m$ 如此大的数量,而 $n$ 相对 $m$ 却又那么小,我们可以想到,这 $m$ 组坐标一定会有相同路径! 那么我们就可以想到,在迷宫中,所有的路径的每一点所能到达的点的数量都是这条路径的长度! ### 毕竟:条条大路通罗马,意味着罗马通着条条大路! 这样,将每个点所在路径的长度都存到整数数组 $anss$ 中,$anss_{i,j}$ 所存的就是所在路径的长度! 最后输入每组 $x,y$ ,我们就可以直接输出 $anss_{x,y}$ 。 ------------ # Code Time ```cpp #include<bits/stdc++.h> using namespace std; int n,t,bx,by,k=2; int tx[]={0,-1,0,1},ty[]={-1,0,1,0};//四个方向不必多说 bool vis[1005][1005];//基本 bfs 需要 char mapp[1005][1005];//基本 bfs 需要 int ansxy[1000010][2],anss[1005][1005]; //重点! ansxy 中存着一条路径的每一个点,而 anss 则是存每点所在路径的长度 void bfs(int ix,int iy){ k=2; queue<int> x,y; x.push(ix),y.push(iy); ansxy[1][0]=ix,ansxy[1][1]=iy; while(!x.empty()){//不空不停 int xx=x.front(), yy=y.front(); for(int i=0;i<4;i++)//基本 bfs 操作 if(mapp[xx+tx[i]][yy+ty[i]]!=mapp[xx][yy]&&!vis[xx+tx[i]][yy+ty[i]]&& xx+tx[i]>=1&&xx+tx[i]<=n&&yy+ty[i]>=1&&yy+ty[i]<=n){ vis[xx+tx[i]][yy+ty[i]]=1; ansxy[k][0]=xx+tx[i],ansxy[k++][1]=yy+ty[i]; //将点的位置记录下来 x.push(xx+tx[i]), y.push(yy+ty[i]); } x.pop(),y.pop(); } for(int i=1;i<k;i++)//放入路径长度 anss[ansxy[i][0]][ansxy[i][1]]=k-1;//次数点的个数即为路径长度 } int main(){ cin>>n>>t; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>mapp[i][j]; //从头到尾遍历一遍:遇到没访问过的(即还没有被某条路径包含)的开始 bfs for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(!vis[i][j]){ vis[i][j]=1; bfs(i,j); } while(t--){ cin>>bx>>by; cout<<anss[bx][by]<<endl; } return 0; } ```