根据题意可知,这题运用了洪水流算法。模板就不再这里进行叙述了。
题目分析:
由题意可知,由1封闭的0才能填2.所有反向来思考洪水流算法,先将整个矩阵的扩大一圈,并使扩大的这一圈的数都为0,之后(方便,下面的遍历),从(0,0)这一点直接bfs。
bfs的过程:
将没有被1包围的0全部排除,之后剩下1和再1内的0。
条件:
遍历四个方向,如果等于0并且这个点没有被遍历过(false),将它加入队列,并将它true(已标记),加入队列。
总结:
将外面的0看作洪水,将1和1内的0看作陆地。直接把外面的0全部遍历就可以了。
#include<iostream>
#define x first
#define y second //宏定义
using namespace std;
typedef pair<int,int> PII; //定义pair类型
const int N=31;
int a[N][N];//数据
int n;
bool st[N][N];//标记是否没遍历
PII q[N*N]; //队列
//我用的是模拟队列,没用stl。
void bfs()
{
int hh=0,tt=0; //队头,队尾
st[0][0]=true; //将起始点标记
q[0]={0,0}; //加入队列
while(hh<=tt) //在队列中
{
auto t=q[hh++]; //取出队头
//stl写法 auto t=q.top(),q.pop();
//或者是q.front(). 这个我有点不确定
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
for(int i=0;i<4;i++) //遍历四个方向
{
int sx=t.x+dx[i],sy=t.y+dy[i]; //现在的坐标
------------
//下面应该也可以写成
if(sx<0||sy<0||sx>n+1||sy>n+1) continue;
if(st[sx][sy]==true) continue;
if(a[sx][sy]!=0) continue;
st[sx][sy]=true;
q[++tt]={sx,sy};
------------ ()
if(sx>=0&&sy>=0&&sx<=n+1&&sy<=n+1&&st[sx][sy]==false&&a[sx][sy]==0) //条件,见上面的说明
{
st[sx][sy]=true; //标记
q[++tt]={sx,sy}; //加入队列
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
bfs();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(st[i][j]==false&&a[i][j]==0) //内部的0,就是被bfs遍历到
cout<<2<<' ';
else
cout<<a[i][j]<<' '; //反之就是遍历过的0和没有被遍历的1.
}
cout<<endl;//或者puts("");
}
return 0;
}
//弱鸡只会bfs,不会dfs。
总体上来说,只要掌握模板皆可写。
接下来,一起加油吧。