codevs【1049】棋盘染色

本文详细解析了一个关于5x5棋盘最少染色数的算法问题,通过迭代+深搜的方式,找出使所有黑色格子连成一块所需的最少染色格子数目。介绍了算法的具体实现过程,包括状态读取、迭代深搜、染色验证等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
有一个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;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值