当前位置: 首页 > news >正文

[枚举涂块]画家问题

画家问题

题目描述

有一个正方形的墙,由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;
}

相关文章:

  • TypeScript 的基础语法
  • FormData传送复杂数据
  • JAVA|PHP|c#爬虫-1688官网自动以图搜图API接口功能实现
  • 位乘积计数-蓝桥
  • 听GPT 讲Rust源代码--library/proc_macro
  • pyDAL一个python的ORM(4) pyDAL查询操作
  • mysql之四大引擎、账号管理以及建库
  • ORACLE Primavera P6, Unifier v23.12 系统分享
  • 从 WasmEdge 运行环境读写 Rust Wasm 应用的时序数据
  • flutter接入扫码枪的扫描结果,其实就是监听键盘输入,从测试到页面显示出来
  • 微服务事务处理:CAP 定理和最终一致性的关系
  • 计算机网络——基础知识汇总(八)
  • uniapp多级动态表单规则
  • Zookeeper-Zookeeper特性与节点数据类型详解
  • 个人财务管理软件Money Pro mac功能特点
  • 0基础学习移动端适配
  • CEF与代理
  • DataBase in Android
  • Docker容器管理
  • ES6之路之模块详解
  • Java 内存分配及垃圾回收机制初探
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • JAVA并发编程--1.基础概念
  • Python进阶细节
  • Redash本地开发环境搭建
  • SQLServer之创建数据库快照
  • Swift 中的尾递归和蹦床
  • underscore源码剖析之整体架构
  • VuePress 静态网站生成
  • vue的全局变量和全局拦截请求器
  • XML已死 ?
  • 测试如何在敏捷团队中工作?
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 前端自动化解决方案
  • 译有关态射的一切
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • MPAndroidChart 教程:Y轴 YAxis
  • Spring Batch JSON 支持
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #android不同版本废弃api,新api。
  • #Linux(make工具和makefile文件以及makefile语法)
  • #QT项目实战(天气预报)
  • #每天一道面试题# 什么是MySQL的回表查询
  • $L^p$ 调和函数恒为零
  • (WSI分类)WSI分类文献小综述 2024
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)视频码率,帧率和分辨率的联系与区别
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存