题目描述 Description
有一个5×5的棋盘,上面有一些格子被染成了黑色,其他的格子都是白色,你的任务的对棋盘一些格子进行染色,使得所有的黑色格子能连成一块,并且你染色的格子数目要最少。读入一个初始棋盘的状态,输出最少需要对多少个格子进行染色,才能使得所有的黑色格子都连成一块。(注:连接是指上下左右四个方向,如果两个黑色格子只共有一个点,那么不算连接)
输入描述 Input Description
输入包括一个5×5的01矩阵,中间无空格,1表示格子已经被染成黑色。
输出描述 Output Description
输出最少需要对多少个格子进行染色
样例输入 Sample Input
11100
11000
10000
01111
11111
样例输出 Sample Output
1
思路:5*5的棋盘,数据量比较小。 在初始输入的过程中,记录下空格的位置。找出在空格中填充1的可能组合(即填1个1,2个1还是n个1能使棋盘联通),填充上1,然后检测棋盘是否联通。
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 5;
bool grids[N][N]; // 地图
bool cpyGrids[N][N]; // 地图的备份
vector<int> blanks; // 存放空格位置
bool isStuff[N*N];
int ptX,ptY; // 记录棋盘中某个点为1的坐标
void input()
{
for (int i = 0; i < N; i++)
{
char s[N+1];
scanf("%s",s);
for (int j = 0; j < N; j++)
{
grids[i][j] = s[j] - '0';
if (!grids[i][j]) // 若是空格,则存储空格的位置
{
blanks.push_back(i*N+j);
}
else
{
ptX = i;
ptY = j;
}
}
}
}
void check(int x,int y)
{
cpyGrids[x][y] = false;
if(x+1 < N && cpyGrids[x+1][y]) check(x+1,y);
if(x-1 >= 0 && cpyGrids[x-1][y]) check(x-1,y);
if(y+1 < N && cpyGrids[x][y+1]) check(x,y+1);
if (y-1 >= 0 && cpyGrids[x][y-1]) check(x,y-1);
}
bool stuff(int start,int n,int cnt)
{
if (n == cnt)
{
memcpy(cpyGrids,grids,sizeof(grids));
check(ptX,ptY);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (cpyGrids[i][j])
{
return false;
}
}
}
return true;
}
for (int i = start; i < blanks.size(); i++)
{
if(!isStuff[blanks[i]]) // 如果没填,则尝试填充 ,枚举的就是空格区域,所以只管填
{
isStuff[blanks[i]] = true;
grids[blanks[i]/N][blanks[i]%N] = true;
if(stuff(i+1,n+1,cnt)) return true;
grids[blanks[i]/N][blanks[i]%N] = false;
isStuff[blanks[i]] = false;
}
}
return false;
}
void fn()
{
for (int i = 1; i <= N*N ; i++) // 尝试向棋盘中填入 0,1,2,...25 个1.
{
if(stuff(0,0,i))
{
printf("%d",i);
break;
}
}
}
int main()
{
input();
fn();
return 0;
}