题意:给你一个0,1矩阵,数字1相当于是围墙,有一些数字0会被数字1完全围住,现在要求你把被围住的数字输出时全部输出2,其余数字输出时原样输出。
思路:被所有的1围住肯定就不和边界接壤了呗,我们就从与边界接壤的0开始搜索,然后求联通快,块里的所有数字0全部标记为1,原先的数字1也标记为1.最后被标记的原样输出,没被标记的输出2就可以了。结果这道题给敲错了,bfs又无限入队了。因为我判断是否入队的条件是,只要下一个 数字不越界并且不是1就入队,但是这样就导致了某个子节点的父节点会重复入队,因为它永远为0且永远不越界。所以正确的判断方法应该是 ,不越界,并且没有被访问过,且不为1.这样就避免了重复入队。
#include<bits/stdc++.h> using namespace std; int n; int w[40][40]; int visit[40][40]; struct node { int dx,dy; }dir[5]; struct node2{ int x,y; }; queue<node2> q; void bfs(int x,int y) { struct node2 a; a.x=x;a.y=y; q.push(a); while(!q.empty()) { node2 b; b=q.front(); q.pop(); for(int i=1;i<=4;i++) { int xx,yy; xx=b.x+dir[i].dx; yy=b.y+dir[i].dy; if(xx>=1&&yy>=1&&xx<=n&&yy<=n) { if(!visit[xx][yy]) { visit[xx][yy]=1; node2 c; c.x=xx;c.y=yy; q.push(c); } } } } return ; } int main() { dir[1].dx=0;dir[1].dy=-1; dir[2].dx=-1;dir[2].dy=0; dir[3].dx=0;dir[3].dy=1; dir[4].dx=1;dir[4].dy=0; cin>>n; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { cin>>w[i][j]; if(w[i][j]==1) visit[i][j]=1; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(i==1||i==n||j==1||j==n) { if(!visit[i][j]) { visit[i][j]=1; bfs(i,j); //cout<<"111111111111 "; } } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(visit[i][j]) cout<<w[i][j]<<" "; else cout<<"2"<<" "; } cout<<" "; } return 0; }