题目描述
有一个由数字 0、1 组成的方阵中,存在一任意形状的封闭区域,封闭区域由数字1 包围构成,每个节点只能走上下左右 4 个方向。现要求只把【最大封闭区域】内的空间填写成2 。
例如: 6×6 的方阵:
6
0 1 0 0 0 0
1 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 1 0 0 0 0
1 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
输入要求
每组测试数据第一行一个整数 n(1≤n≤30)
接下来 n 行,由 0 和 1 组成的 n×n 的方阵。
封闭区域内至少有一个0,测试数据保证最大区域只有一个。
输出要求
已经填好数字 2 的完整方阵。(每个数字后面有一个空格!)
输入样例
6
0 1 0 0 0 0
1 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 1 0 0 0 0
1 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
答案:深搜
#include<iostream>
#include<cstring>
using namespace std;
int a[40][40];
int n;
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // 右 左 下 上
int cnt = 0; // 某一个封闭区域的大小
int maxn = 0; // 最大封闭区域大小
int id = 3; // 染色区域的编号
int max_id = id;
void dfs(int x, int y)
{
if(x<0 || x>n+1 || y<0 || y>n+1 || a[x][y]!=0) //禁止染色的判断 x<0 || x>n+1 || y<0 || y>n+1为矩阵4个边
return ;
a[x][y] = id; //染色
cnt++;
for(int i=0; i<4; i++){
dfs(x+dir[i][0], y+dir[i][1]);
}
}
int main()
{
cin >> n;
memset(a, 0, sizeof(a));
int i;
// 输入数据
for( i=1; i<=n; i++)
for(int j=1; j<=n; j++){
int k;
cin >> k;
a[i][j] = k;
}
//将边缘的0和其连接块都染色
dfs(0, 0);
id++;
for( i=2; i<n; i++)
for(int j=2; j<n; j++){
cnt = 0;
// 搜索每一个元素,找到最大封闭区域
dfs(i, j);
//cout << cnt;
if(cnt > maxn){
maxn = cnt;
max_id = id;
}
id++;
}
// 输出
for( i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(a[i][j] == 1)
cout << a[i][j] << " ";
else if(a[i][j] != max_id)
cout << '0' << " ";
else
cout << '2' << " ";
}
cout << endl;
}
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
int a[40][40];
int n;
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // 右 左 下 上
/*
-----------
| 0 | 1
-----------
0 | 0 | 1
-----------
1 | 0 |-1
-----------
2 | 1 | 0
-----------
3 |-1 | 0
-----------
*/
int cnt = 0; // 某一个封闭区域的大小
int maxn = 0; // 最大封闭区域大小
int id = 3; // 染色区域的编号
int max_id = id;
void dfs(int x, int y){
if(x<0 || x>n+1 || y<0 || y>n+1 || a[x][y]!=0) //碰到不为0的就会缩回去
return ;
a[x][y] = id;
cnt++;
for(int i=0; i<4; i++){
dfs(x+dir[i][0], y+dir[i][1]);
}
}
int main()
{
cin >> n;
memset(a, 0, sizeof(a)); //全部置0
int i;
// 输入数据 ,外圈为0
for( i=1; i<=n; i++)
for(int j=1; j<=n; j++){
int k;
cin >> k;
a[i][j] = k;
}
//将边缘的0和其连接块都染色
dfs(0, 0);
id++;
for( i=2; i<n; i++)// 由于输入的矩阵最外圈不可能是封闭的
for(int j=2; j<n; j++){
cnt = 0;
// 搜索每一个元素,找到最大封闭区域
dfs(i, j);
//cout << cnt;
if(cnt > maxn){
maxn = cnt;
max_id = id;
}
id++;
}
// 输出
cout<<endl;
for( i=0; i<=n; i++){ //相当于现有矩阵往里缩2层开始
for(int j=0; j<=n+1; j++){//一列一列的查询
if(a[i][j]/10==0)
cout <<" "<< a[i][j] << " ";
else
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
}