题目描述
由数字 0 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 1 构成,围圈时只走上下左右 4 个方向。现要求把闭合圈内的所有空间都填写成 2 .例如:6×6 的方阵( n=6 ),涂色前和涂色后的方阵如下:
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
输入输出格式
输入格式:
每组测试数据第一行一个整数(1≤n≤30)
接下来 n 行,由 0 和 1 组成的n×n 的方阵。
方阵内只有一个闭合圈,圈内至少有一个 0 。
//感谢黄小U饮品指出本题数据和数据格式不一样. 已修改(输入格式)
输出格式:
已经填好数字 2 的完整方阵。
输入输出样例
输入样例#1
6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
输出样例#1
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
思路
本题我用的dfs,但坑非常多。这是一道类似于连通块问题的题目。
因为只有0和1,且0分为两种,所以我们先把它手动分成三个数。把圈外0的用dfs先变成其他的数,最后把地图扫一遍,把没被改变的0(即圈内的0)变成需要的数2。 同时要是检测到圈外数(刚刚dfs更改的)把它变回0就OK啦!
40分代码:
#include <stdio.h>
#include <iostream>
using namespace std;
int tox[5]={0,1,0,-1,0};//4个方向
int toy[5]={0,0,1,0,-1};
int n;
int a[41][41];//地图
inline void dfs(int x,int y)
{
register int i;
if(x>=0 && x<=n && y>=0 && y<=n)//如果在地图内
{
if(a[x][y]==1 || a[x][y]==3)//如果是1或者把0改成3的坐标(已经搜索过的坐标)
{
return;
}
else
{
a[x][y]=3;//把是0的点变成另外一个数字
for(i=1;i<=4;i++)//搜索4个方向
{
int x1=x+tox[i];//尝试下一个点
int y1=y+toy[i];
{
dfs(x1,y1);
}
}
}
}
return;
}
int main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>a[i][j];//输入地图
}
}
dfs(1,1);//开始搜索
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(a[i][j]==3)//把外面的0改成0
{
a[i][j]=0;
}
else if(a[i][j]==0)//如果是圈里的0,改成2.因为dfs是找外面的0的,里面的0没有找。
{
a[i][j]=2;
}
}
}
for(i=1;i<=n;i++,cout<<endl)
{
for(j=1;j<=n;j++)
{
cout<<a[i][j]<<' ';//打印地图
}
}
return 0;
}
很可惜,这个程序,只能得40分。
dfs在先搜索的时候应该搜索到矩阵的外面一圈(0, n + 1) 否则的话就会出现错误(边缘处被涂色)。
输入:
6
0 0 1 1 1 0
1 1 1 0 1 0
1 0 0 0 0 1
1 1 0 1 1 1
0 1 0 1 0 0
0 1 1 1 0 0
正确输出:
0 0 1 1 1 0
1 1 1 2 1 0
1 2 2 2 2 1
1 1 2 1 1 1
0 1 2 1 0 0
0 1 1 1 0 0
#include <stdio.h>
#include <iostream>
using namespace std;
int tox[5]={0,1,0,-1,0};//4个方向
int toy[5]={0,0,1,0,-1};
int n;
int a[41][41];//地图
inline void dfs(int x,int y)
{
register int i;
if(x>=0 && x<=n+1 && y>=0 && y<=n+1)//如果在地图内
{//这就是问题所在:(结合第62行)为dfs是找外面的0的,里面的0没有找,但如果是这个数据,右下角的4个0不能被搜索到,所以要多搜1圈,即n+1
/*
6
0 0 1 1 1 0
1 1 1 0 1 0
1 0 0 0 0 1
1 1 0 1 1 1
0 1 0 1 0 0
0 1 1 1 0 0
*/
if(a[x][y]==1 || a[x][y]==3)//如果是1或者把0改成3的坐标(已经搜索过的坐标)
{
return;
}
else
{
a[x][y]=3;//把是0的点变成另外一个数字
for(i=1;i<=4;i++)//搜索4个方向
{
int x1=x+tox[i];//尝试下一个点
int y1=y+toy[i];
{
dfs(x1,y1);
}
}
}
}
return;
}
int main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>a[i][j];//输入地图
}
}
dfs(1,1);//开始搜索
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(a[i][j]==3)//把外面的0改成0
{
a[i][j]=0;
}
else if(a[i][j]==0)//如果是圈里的0,改成2.因为dfs是找外面的0的,里面的0没有找。
{
a[i][j]=2;
}
}
}
for(i=1;i<=n;i++,cout<<endl)
{
for(j=1;j<=n;j++)
{
cout<<a[i][j]<<' ';//打印地图
}
}
return 0;
}
尽管做了一系列的的修改,却还是80分。
错误请看代码。
#include <stdio.h>
#include <iostream>
using namespace std;
int tox[5]={0,1,0,-1,0};//4个方向
int toy[5]={0,0,1,0,-1};
int n;
int a[41][41];//地图
inline void dfs(int x,int y)
{
register int i;
if(x>=0 && x<=n+1 && y>=0 && y<=n+1)//如果在地图内
{
if(a[x][y]==1 || a[x][y]==3)//如果是1或者把0改成3的坐标(已经搜索过的坐标)
{
return;
}
else
{
a[x][y]=3;//把是0的点变成另外一个数字
for(i=1;i<=4;i++)//搜索4个方向
{
int x1=x+tox[i];//尝试下一个点
int y1=y+toy[i];
{
dfs(x1,y1);
}
}
}
}
return;
}
int main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>a[i][j];//输入地图
}
}
dfs(0,0);//这是相对80分的错误:如果要多搜1圈,那么就要从0,0开始搜。
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(a[i][j]==3)//把外面的0改成0
{
a[i][j]=0;
}
else if(a[i][j]==0)//如果是圈里的0,改成2.因为dfs是找外面的0的,里面的0没有找。
{
a[i][j]=2;
}
}
}
for(i=1;i<=n;i++,cout<<endl)
{
for(j=1;j<=n;j++)
{
cout<<a[i][j]<<' ';//打印地图
}
}
return 0;
}