题目描述
有一个5×5的棋盘,上面有一些格子被染成了黑色,其他的格子都是白色,你的任务是对棋盘一些格子进行染色,使得所有的黑色格子能连成一块,并且你染色的格子数目要最少。读入一个初始棋盘的状态,输出最少需要对多少个格子进行染色,才能使得所有的黑色格子都连成一块。(注:连接是指上下左右四个方向,如果两个黑色格子只共有一个点,那么不算连接)
输入描述
输入包括一个5×5的01矩阵,中间无空格,1表示格子已经被染成黑色。
输出描述
输出最少需要对多少个格子进行染色
样例输入
11100
11000
10000
01111
11111
样例输出
1
分析
这道题需要使用迭代+深搜。
#include<iostream>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
char a[5][5],visited[5][5];
int depth;//表示染色的个数
int dir[][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool isValid(int x,int y)
{
return (x >= 0 && x < 5) && (y >= 0 && y < 5) && (visited[x][y] == 0) && (a[x][y] == '1');
}
int f(int x,int y)//本质也是深搜,用来寻找相连的黑色格子
{
if(isValid(x,y)) {
visited[x][y] = 1;
for(int k = 0; k < 4; k++) {
int i = x + dir[k][0];
int j = y + dir[k][1];
f(i,j);
}
return 1;
}
return 0;
}
bool check()
{
int num = 0;
memset(visited,0,sizeof(visited));
for(int i = 0; i < 5; i++)
for(int j = 0; j < 5; j++)
num += f(i,j);
return num == 1;//判断是不是都连到一块了
}
//m表示是第m+1个格子(二维数组从左到右,从上到下,m从0开始),step记录染了多少个格子
bool dfs(int m,int step)
{
if(m == 25 || step == depth) return check();//当染了depth块格子,就进行检查
int x = m / 5;//这里可以得到格子的下标x和y
int y = m % 5;
if(dfs(m + 1,step)) return true;//这里表示不染
if(a[x][y] == '0') {//题目的意思是只对白色格子进行染色
a[x][y] = '1';
if(dfs(m + 1,step + 1)) {//这里表示把白色染成黑色,继续搜索
a[x][y] = '0';
return true;
}
a[x][y] = '0';
}
return false;
}
int main()
{
for(int i = 0; i < 5; i++)
for(int j = 0; j < 5; j++)
cin >> a[i][j];
for(depth = 1; depth < INF; depth++)//根据题目意思,可以得到解
if(dfs(0,0)) break;
cout << depth << endl;
return 0;
}