[枚举涂块]画家问题

画家问题

题目描述

有一个正方形的墙,由N*N个正方形的砖组成,其中一些砖是白色的,另外一些砖是黄色的。Bob是个画家,想把全部的砖都涂成黄色。但他的画笔不好使。当他用画笔涂画第(i, j)个位置的砖时, 位置(i-1, j)、 (i+1, j)、 (i, j-1)、 (i, j+1)上的砖都会改变颜色。请你帮助Bob计算出最少需要涂画多少块砖,才能使所有砖的颜色都变成黄色。

关于输入

第一行是个整数t(1≤t ≤20),表示要测试的案例数。然后是t个案例。每个案例的首行是一个整数n (1≤n ≤15),表示墙的大小。接下来的n行表示墙的初始状态。每一行包含n个字符。第i行的第j个字符表示位于位置(i,j)上的砖的颜色。“w”表示白砖,“y”表示黄砖。

关于输出

每个案例输出一行。如果Bob能够将所有的砖都涂成黄色,则输出最少需要涂画的砖数,否则输出“inf”。

例子输入
2
3
yyy
yyy
yyy
5
wwwww
wwwww
wwwww
wwwww
wwwww
例子输出
0
15
解题分析

要解决这个问题,我们先去思考一下,怎么涂才能把全部区块涂满呢?又有多少种的解法?显然,我们没有办法直接一眼就看出来怎么去涂,并且题目也要求我们去求一个最少的操作步骤,所以枚举是不可避免的,关键是我们如何去枚举呢?

其实我们一行一行地涂,考虑第一行每一个区块是否涂就可以了,后面的每一行都是根据前一行的状态去确定是否填涂的,如果前一行中有白色的砖块,那么它的下一行的这个砖块必然要涂,否则不可能把全部砖块都涂满,这样的话问题就清晰起来了,其实我们只要去枚举第一行的全部情况即可,每个方块只有涂和不涂两种状态,所以说,最多也就2的15次方种情况,这是一个可以接受的数字。

最后只要检查最后一行有没有被涂满就行了。

  1. 首先,我们定义一个递归函数draw,用于将指定位置的砖及其周围砖的颜色进行反转。具体操作是,如果砖是白色的,则改为黄色,反之亦然。同时,将周围砖的颜色也进行反转。
  2. 然后,我们定义一个递归函数print,用于检查当前墙的状态是否可以全部涂成黄色。具体操作是,从上到下每一行进行遍历:
    • 如果是第一行,则遍历每一列,将该位置及其周围砖的颜色进行反转,并设置count数组的相应位置为1(表示已经涂过颜色)。
    • 如果是其他行,则遍历上一行中颜色为白色的位置,在该位置上进行反转,并设置count数组的相应位置为1(表示已经涂过颜色)。
    • 递归调用print函数,进行下一行的涂色操作。
    • 在每一行结束时,检查最后一行是否所有砖都变为黄色,如果是,则计算涂色的砖数ans,并将ans与当前最小涂色砖数ANS进行比较,取较小值。
  3. 接下来,我们定义一个递归函数fill,用于枚举第一行中的每个位置是否涂色。具体操作是,对于每个位置,递归调用fill函数,分别设置该位置涂色和不涂色,并进行下一行的涂色操作。
  4. 在主函数中,读入测试案例的数量t,并进行t次测试。对于每个测试案例,读入墙的大小n和初始状态的墙面颜色。初始化一个标记数组is,用于记录第一行中每个位置是否涂色。初始化最小涂色砖数ANS为无穷大。
  5. 调用fill函数,开始进行所有位置的枚举涂色操作。在fill函数中,递归调用fill函数,对第一行中的每个位置进行设置涂色和不涂色。在每个位置上进行设置涂色或不涂色后,调用print函数,进行下一行的涂色操作。
  6. 在print函数中,检查是否最后一行的所有砖都变为黄色。如果是,则计算涂色的砖数ans,并将ans与当前最小涂色砖数ANS进行比较,取较小值。
  7. 在主函数中,将最小涂色砖数ANS输出。如果ANS为无穷大,则输出"inf"。
代码实现
#include <iostream>
#include <cstring>
using namespace std;int t=0,n=0,ANS=1e9;;
char board1[16][16],board2[16][16];
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
bool is[16]={0}, count[16][16];void draw(int x,int y){if(board2[x][y]=='w') board2[x][y]='y';else board2[x][y]='w';for(int i=0;i<4;i++){int nx=x+dx[i],ny=y+dy[i];if(nx>=1 && nx<=n && ny>=1 && ny<=n){if(board2[nx][ny]=='w') board2[nx][ny]='y';else board2[nx][ny]='w';}}
}void print(int row){if(row==n+1){for(int i=1;i<=n;i++){if(board2[n][i]=='w'){return;}}int ans=0;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(count[i][j]) ans++;}ANS=min(ANS,ans);return;}if(row==1){for(int i=1;i<=n;i++){if(is[i]){draw(row,i);count[row][i]=1;}}print(row+1);}else{for(int i=1;i<=n;i++){if(board2[row-1][i]=='w'){draw(row,i);count[row][i]=1;}}print(row+1);}
}void fill(int step){if(step==n+1){memcpy(board2,board1,sizeof(board1));memset(count,0,sizeof(count));print(1);return;}for(int i=0;i<2;i++){if(i==0){is[step]=1;fill(step+1);}else{is[step]=0;fill(step+1);}}
}int main(){scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){scanf(" %c",&board1[i][j]);}}memset(is,0,sizeof(is));ANS=1e9;fill(1);if(ANS!=1e9)printf("%d\n",ANS);elseprintf("inf\n");}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/589142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

劫持 PE 文件:新建节表并插入指定 DLL 文件

PE格式简介 PE(Portable Executable)格式&#xff0c;是微软Win32环境可移植可执行文件(如exe、dll、vxd、sys和vdm等)的标准文件格式。PE格式衍生于早期建立在VAX(R)VMS(R)上的COFF(Common Object File Format)文件格式。 Portable 是指对于不同的Windows版本和不同的CPU类型上…

UIToolKit使用心得

起因 因为那个uitoolkit自己写了一套graphView&#xff0c;所以想着来用用但是用完之后发现也不过如此 怎么构建自己的组件 我在继承Node之后想修改node的样式该怎么办呢是这样的。先用pick点击默认的node节点元素- 在pick默认创建的node节点之后&#xff0c;可以把它的uxml…

类的加载顺序问题-demo展示

面试的的时候经常会被问到包含静态代码块、实例代码块和构造器等代码结构的加载顺序问题&#xff0c;下面借用一个面试题&#xff0c;回顾一下类的代码加载顺序。 public class AooTest {public static void main(String[] args) {AooTest.f1();}static AooTest test1 new Ao…

RedisTemplate序列化

SpringBoot整合Redis&#xff0c;配置RedisTemplate序列化。如果使用StringRedisTemplate&#xff0c;那么不需要配置序列化&#xff0c;但是StringRedisTemplate只能存储简单的String类型数据&#xff0c;如图&#xff1a; 如果使用StringRedisTemplate存储一个常规对象&#…

步进电机为什么叫步进电机,内部结构是什么,工作原理是什么,有什么特点,什么用途。

问题描述&#xff1a;步进电机为什么叫步进电机&#xff0c;内部结构是什么&#xff0c;工作原理是什么&#xff0c;有什么特点&#xff0c;什么用途。 问题解答&#xff1a; "步进"一词表示电机按照固定的步进角度运动。步进电机以控制脉冲信号来驱动转子按照一定的…

3D视觉-相机选用的原则

鉴于不同技术方案都有其适用的场景&#xff0c;立体相机的选型讲究的原则为“先看用途&#xff0c;再看场景&#xff0c;终评精度”&#xff0c;合适的立体相机在方案中可以起到事半功倍的效果。从用途上来进行划分&#xff0c;三维视觉方案主要应用在两个方向&#xff1a;测量…

JavaScript中alert、prompt 和 confirm区别及使用【通俗易懂】

✨前言✨   本篇文章主要在于&#xff0c;让我们看几个与用户交互的函数&#xff1a;alert&#xff0c;prompt 和confirm的使用及区别 &#x1f352;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f352;博主将持续更新学习记录收获&…

PiflowX组件-WriteToUpsertKafka

WriteToUpsertKafka组件 组件说明 以upsert方式往Kafka topic中写数据。 计算引擎 flink 有界性 Streaming Upsert Mode 组件分组 kafka 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许值是否必填描述例子kafka_h…

阿里开源大模型 Qwen-72B 私有化部署

近期大家都知道阿里推出了自己的开源的大模型千问72B&#xff0c;据说对于中文非常友好&#xff0c;在开源模型里面&#xff0c;可谓是名列前茅。 千问拥有有强大的基础语言模型&#xff0c;已经针对多达 3 万亿个 token 的多语言数据进行了稳定的预训练&#xff0c;覆盖领域、…

【Java】JUC并发编程(重量锁、轻量锁、偏向锁)

JUC并发编程 预备&#xff1a; 创建一个maven工程&#xff0c;导入lombok和logback的依赖。 1、基础概念 1、进程与线程 **进程&#xff1a;**程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至 CPU &#xff0c;数…

Golang不可不知的7个并发概念

并发性支持是Golang最重要的原生特性之一&#xff0c;本文介绍了Golang中和并发性相关的7个概念。原文: Golang: 7 must-know concurrency related concepts 并发是Go编程语言的基本特性&#xff0c;意味着程序可以同时执行多个任务。Golang的并发独特而强大&#xff0c;其内置…

【Linux操作系统】探秘Linux奥秘:文件系统的管理与使用

&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《操作系统实验室》&#x1f516;诗赋清音&#xff1a;柳垂轻絮拂人衣&#xff0c;心随风舞梦飞。 山川湖海皆可涉&#xff0c;勇者征途逐星辉。 目录 &#x1fa90;1 初识Linux OS &…

【数据结构】栈和队列(队列的基本操作和基础知识)

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm1001.2014.3001.5482 ​ 目录 前言 队列 队列的概念和结构 队列的…

二叉树详解(深度优先遍历、前序,中序,后序、广度优先遍历、二叉树所有节点的个数、叶节点的个数)

目录 一、树概念及结构(了解) 1.1树的概念 1.2树的表示 二、二叉树概念及结构 2.1概念 2.2现实中的二叉树&#xff1a; 2.3数据结构中的二叉树&#xff1a; 2.4特殊的二叉树&#xff1a; 2.5 二叉树的存储结构 2.51 顺序存储&#xff1a; 2.5.2 链式存储&…

CSS2_基础学习

CSS2_基础学习 一、css基础知识二、css选择器2.0 选择器的优先级2.1 CSS基本选择器2.2 复合选择器2.2.1. 交集选择器2.2.2. 并集选择器2.2.3. 后代选择器&#xff08;加空格&#xff09;2.2.4. 子代选择器2.2.5. 兄弟选择器2.2.6. 属性选择器2.2.7. 伪类选择器2.2.8. 伪元素选择…

微信小程序发送模板消息-详解【有图】

前言 在发送模板消息之前我们要首先搞清楚微信小程序的逻辑是什么&#xff0c;这只是前端的一个demo实现&#xff0c;建议大家在后端处理&#xff0c;前端具体实现&#xff1a;如下图 1.获取小程序Id和密钥 我们注册完微信小程序后&#xff0c;可以在开发设置中看到以下内容&a…

navicat premium历史版本下载及更新navicat premium15 永久(使用)有效期

1、navicat premium介绍 Navicat Premium 是一套可创建多个连接的数据库开发工具&#xff0c;让你从单一应用程序中同时连接 MySQL、Redis、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite 。它与 GaussDB 、OceanBase 数据库及 Amazon RDS、Amazon Aurora、Amaz…

基于简化版python+VGG+MiniGoogLeNet的智能43类交通标志识别—深度学习算法应用(含全部python工程源码)+数据集+模型(一)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python环境Anaconda环境 模块实现1. 数据预处理 相关其它博客工程源代码下载其它资料下载 前言 本项目专注于解决出国自驾游特定场景下的交通标志识别问题。借助Kaggle上的丰富交通标志数据集&#xff0c;我们采用了VGG和G…

推荐系统中 排序策略 CTR 动态加权平均法

CTR&#xff08;Click-Through Rate&#xff09;动态加权平均法是一种用于计算广告点击率的方法&#xff0c;其中每个点击率被赋予一个权重&#xff0c;这个权重可以随着时间、事件或其他因素而动态调整。这种方法旨在更灵活地反映广告点击率的变化&#xff0c;使得最近的数据更…

Mybatis 事务接口

当我们从数据源中得到一个可用的数据库连接之后&#xff0c;就可以开启一个数据库事务了&#xff0c;事务成功开启之后&#xff0c;我们才能修改数据库中的数据。 在修改完成之后&#xff0c;我们需要提交事务&#xff0c;完成整个事务内的全部修改操作&#xff0c;如果修改过…