思路解析:
这里我们采用一种间接的方法,即先找出那些不在闭合圈内的 0,也就是从方阵边界能够通过仅经过 0 到达的 0,然后将剩余未被标记的 0 判定为在闭合圈内,进而将它们替换为 2。而找不在闭合圈内的 0可以采用深度优先搜索或广度优先搜索对方阵的第一行、最后一行、第一列和最后一列的每个位置开始进行上下左右四个相邻位置进行搜索。
代码展示:
方法一:深度优先搜索
#include<stdio.h>
int n;
//存储输入的矩阵
int m[30][30];
//标记每个位置是否被访问过
int visited[30][30];
//方向数组,用于表示上下左右四个方向
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
/*
深度优先搜索函数:
若当前位置越界、为 1 或者已被访问过,则直接返回。
标记当前位置为已访问。
递归地对当前位置的上下左右四个相邻位置进行深度优先搜索。
*/
void dfs(int x,int y);
int main()
{
int i,j,k;
//输入
scanf("%d",&n);
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%d",&m[i][j]);
}
}
for(i=0;i<n;i++){
dfs(0,i);//从方阵的第一行的每个位置开始进行深度优先搜索,标记所有能够到达的 0。
dfs(n-1,i);//从方阵的最后一行的每个位置开始进行深度优先搜索,标记所有能够到达的 0。
dfs(i,0);//从方阵的第一列的每个位置开始进行深度优先搜索,标记所有能够到达的 0。
dfs(i,n-1);//从方阵的最后一列的每个位置开始进行深度优先搜索,标记所有能够到达的 0。
}
//将圈内的0变成2
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(!visited[i][j]&&m[i][j]==0){
m[i][j]=2;
}
}
}
//输出
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d ",m[i][j]);
}
printf("\n");
}
return 0;
}
void dfs(int x,int y)
{
int xn,yn;
if(x<0||y<0||x>=n||y>=n||m[x][y]==1||visited[x][y]==1){
return ;
}
visited[x][y]=1;
for(int i=0;i<4;i++){
xn=x+dx[i];
yn=y+dy[i];
dfs(xn,yn);
}
}
方法二:广度优先搜索
#include<stdio.h>
int n;
//存储输入的矩阵
int m[30][30];
//标记每个位置是否被访问过
int visited[30][30];
//方向数组,用于表示上下左右四个方向
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
typedef struct
{
int x;
int y;
}Coord;
typedef struct{
Coord base[30*30];
int front;
int rear;
}Queue;
Queue a;
void InitQueue();//队列初始化
int Isempty();//判断队列是否为空
void Enqueue(int x0,int y0);//入队
Coord Dequeue();//出队,并返回出队后的对头元素
void bfs(int x0,int y0); //广度优先搜索
int main()
{
int i,j,k;
InitQueue();//队列初始化
//输入
scanf("%d",&n);
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%d",&m[i][j]);
}
}
for(i=0;i<n;i++){
bfs(0,i);//从方阵的第一行的每个位置开始进行广度优先搜索,标记所有能够到达的 0。
bfs(n-1,i);//从方阵的最后一行的每个位置开始进行广度优先搜索,标记所有能够到达的 0。
bfs(i,0);//从方阵的第一列的每个位置开始进行广度优先搜索,标记所有能够到达的 0。
bfs(i,n-1);//从方阵的最后一列的每个位置开始进行广度优先搜索,标记所有能够到达的 0。
}
//将圈内的0变成2
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(!visited[i][j]&&m[i][j]==0){
m[i][j]=2;
}
}
}
//输出
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d ",m[i][j]);
}
printf("\n");
}
/* for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d ",visited[i][j]);
}
printf("\n");
}*/
return 0;
}
void InitQueue()
{
a.front=0;
a.rear=0;
return ;
}
int Isempty()
{
if(a.front==a.rear) return 1;//返回1,表示队列为空
else return 0;//返回0,表示队列不空
}
void Enqueue(int x0,int y0)
{
if(a.rear-a.front==900) return;
a.base[a.rear].x=x0;
a.base[a.rear].y=y0;
a.rear++;
}
Coord Dequeue()
{
a.front++;
return a.base[a.front];
}
void bfs(int x0,int y0)
{
int i,j,xn,yn;
Coord current;//存放队头元素
if(visited[x0][y0]||m[x0][y0])return ;//若已被访问过或 m[x0][y0]=1则不需要进行广度优先搜索
current.x=x0;
current.y=y0;
visited[current.x][current.y]=1;
Enqueue(current.x,current.y);
while(!Isempty())
{
for(i=0;i<4;i++){
xn=current.x+dx[i];
yn=current.y+dy[i];
if(xn>=0&&yn>=0&&xn<n&&yn<n&&!visited[xn][yn]&&m[xn][yn]==0){
Enqueue(xn,yn);//将其相邻的未访问节点加入队列
visited[xn][yn]=1;
}
}
current=Dequeue();
}
return ;
}