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

费解的开关

费解的开关

你玩过“拉灯”游戏吗?

25 盏灯排成一个 5×5 的方形。

每一个灯都有一个开关,游戏者可以改变它的状态。

每一步,游戏者可以改变某一个灯的状态。

游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。

我们用数字 1表示一盏开着的灯,用数字 0 表示关着的灯。

下面这种状态

10111
01101
10111
10000
11011

在改变了最左上角的灯的状态后将变成:

01111
11101
10111
10000
11011

再改变它正中间的灯后状态将变成:

01111
11001
11001
10100
11011

给定一些游戏的初始状态,编写程序判断游戏者是否可能在 6 步以内使所有的灯都变亮。

输入格式

第一行输入正整数 n,代表数据中共有 n个待解决的游戏初始状态。

以下若干行数据分为 n 组,每组数据有 5 行,每行 5 个字符。

每组数据描述了一个游戏的初始状态。

各组数据间用一个空行分隔。

输出格式

一共输出 n 行数据,每行有一个小于等于 6 的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。

对于某一个游戏初始状态,若 6 步以内无法使所有灯变亮,则输出 −1。

数据范围

0<n≤500

输入样例:
3
00111
01011
10001
11010
1110011101
11101
11110
11111
1111101111
11111
11111
11111
11111

输出样例:

3
2
-1

解析:

观察这个题目首先可以把他当作一个典型的01图标问题,解决这种问题我们一般使用dfs深度遍历搜索

在这里先使用递归来解题,感兴趣的同学可以把他翻译成遍历。

针对于题目给的数组,先把他化成图,

10111
01101
10111
10000
11011

image-20250119162929805

我们可以试着玩游戏一样把他全点亮,该怎么做呐?

首先在第一行不变的前提下(因为要保护第一行,如果直接动第一行会造成无限的死循环,前后的操作会彼此影响,导致不断重复)

我们操作第二行,点击第二行的第一个

image-20250119163222758

第一行就解脱了,这时我们专注于操作第二行就可以了,同理在保护第二行的前提下,所以我们只能操作第三行。

打开(1,2)这个开关

image-20250119163533925

为了点亮(2,2)所以点击(2,3)

image-20250119163634665

为了点亮(4,2)关闭开关(4,3)

image-20250119163819252

至此前两行操作完成,点击(1,4)

image-20250119163946291

依次点击(2,4),(3,4),(5,4)得到

image-20250119164207101

操作最后一行得到:

image-20250119164751196

很显然这种状态无法完成。

因为我们对下面的每一行的操作有大量的重复工作,比如说在保护第二行的基础上对第三行进行操作,以此类推,我们完全可以把它封装成一个函数来实现。

int check(int cnt)//这里的cnt其实是我们传入的k(已经执行的操作数)
{int sum=cnt;for(int i=1;i<=5;i++)for(int j=1;j<=5;j++)b[i][j]=a[i][j];//复制出一个可操作数组for(int i=1;i<=4;i++)//不对最后一行进行操作,因为最后一行不能在通过保护最后一行来操作下一行来实现了。{for(int j=1;j<=5;j++){if(!b[i][j])//找到熄灭的灯{sum++;b[i][j]=!b[i][j];//把目标开关下面的开关点亮,再把它四周的开关取反b[i+1][j]=!b[i+1][j];b[i+1][j-1]=!b[i+1][j-1];b[i+1][j+1]=!b[i+1][j+1];b[i+2][j]=!b[i+2][j];}}}for(int i=1;i<=5;i++)if(!b[5][i])return Inf;//检测最后一行,如果存在熄灭的灯就说明这次递归失败,无解return sum;//成功则返回操作数
}

在代码写到这里的时候我们发现。我们并没有对第一行进行过任何的操作,很明显这样会漏解。

我们延续这种思路其实在遍历每一种情况的时候无非是选或者不选两种情况。这时我们就得出了状态转移方程

image-20250119165740588

这里的cnt表示列,k表示操作数,当操作数+1的时候表示打开开关,操作数不变时表示没有操作。cnt+1表示前进一列

由此我们可以写出一个简单个dfs

int dfs(int cnt,int k)
{if(cnt>5)//到达第5列以后的判断(check)//按下开关时对周围开关的操作dfs(cnt+1,k+1);//按下这个开关//写递归最重要的就是还原案发现场dfs(cnt+1,k);//不按下这个开关
}

在这里我们只对第一行的操作进行了递归,为什么不对每一行都进行递归呐?

因为针对于下面的操作都是寻找未打开的开关有明确的指向性,而对于第一行的操作没有明确的目的,我们只是为了不遗漏答案。

int dfs(int cnt,int k)
{if(cnt>5){ans=min(ans,check(k));//对每一种合法操作进行比较寻找操作数最小的操作数//ans的初值设为IMT_MAX;return 0;}//按下开关时对周围开关的操作a[1][cnt]=!a[1][cnt];a[1][cnt-1]=!a[1][cnt-1];a[1][cnt+1]=!a[1][cnt+1];a[2][cnt]=!a[2][cnt];dfs(cnt+1,k+1);//按下这个开关//写递归最重要的就是还原案发现场a[1][cnt]=!a[1][cnt];a[1][cnt-1]=!a[1][cnt-1];a[1][cnt+1]=!a[1][cnt+1];a[2][cnt]=!a[2][cnt];dfs(cnt+1,k);//不按下这个开关
}

设计主函数

int main()
{scanf("%d",&t);while(t--){for(int i=1;i<=5;i++)for(int j=1;j<=5;j++)scanf("%1d",&a[i][j]);ans=Inf;dfs(1,0);if(ans<7)printf("%d\n",ans);//操作数是否小于等于6步。else printf("-1\n");}return 0;
}

完整代码:

#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define Inf 0x3f3f3f
#define ll long long
using namespace std;
int t;
int ans;
int a[10][10];
int b[10][10];
int check(int cnt)//判断第一行的条件是否成立
{int sum=cnt;for(int i=1;i<=5;i++)for(int j=1;j<=5;j++)b[i][j]=a[i][j];for(int i=1;i<=4;i++){for(int j=1;j<=5;j++){if(!b[i][j]){sum++;b[i][j]=!b[i][j];b[i+1][j]=!b[i+1][j];b[i+1][j-1]=!b[i+1][j-1];b[i+1][j+1]=!b[i+1][j+1];b[i+2][j]=!b[i+2][j];}}}for(int i=1;i<=5;i++)if(!b[5][i])return Inf;return sum;}
int dfs(int cnt,int k)
{if(cnt>5){ans=min(ans,check(k));return 0;}a[1][cnt]=!a[1][cnt];a[1][cnt-1]=!a[1][cnt-1];a[1][cnt+1]=!a[1][cnt+1];a[2][cnt]=!a[2][cnt];dfs(cnt+1,k+1);//按下这个开关a[1][cnt]=!a[1][cnt];a[1][cnt-1]=!a[1][cnt-1];a[1][cnt+1]=!a[1][cnt+1];a[2][cnt]=!a[2][cnt];dfs(cnt+1,k);//不按下这个开关
}
int main()
{scanf("%d",&t);while(t--){for(int i=1;i<=5;i++)for(int j=1;j<=5;j++)scanf("%1d",&a[i][j]);ans=Inf;dfs(1,0);if(ans<7)printf("%d\n",ans);else printf("-1\n");}return 0;
}

相关文章:

费解的开关

费解的开关 你玩过“拉灯”游戏吗&#xff1f; 25 盏灯排成一个 55 的方形。 每一个灯都有一个开关&#xff0c;游戏者可以改变它的状态。 每一步&#xff0c;游戏者可以改变某一个灯的状态。 游戏者改变一个灯的状态会产生连锁反应&#xff1a;和这个灯上下左右相邻的灯也…...

【机器学习】机器学习引领数学难题攻克:迈向未知数学领域的新突破

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 一、引言 在数学的浩瀚领域中&#xff0c;存在着诸多长期未解的难题&#xff0c;这些难题犹如高耸的山峰&#xff0c;吸引着无数数…...

Qt之QDjango-db的简单使用

QDjango是一款由C编写、依托于Qt库的Web开发框架&#xff0c;其设计理念受到了广受欢迎的Python框架Django的影响。这个项目旨在提供一个高效、灵活且易于使用的工具集&#xff0c;帮助开发者构建高质量的Web应用。其项目地址: https://gitcode.com/gh_mirrors/qd/qdjango&…...

缓存、数据库双写一致性解决方案

双写一致性问题的核心是确保数据库和缓存之间的数据同步&#xff0c;以避免缓存与数据库数据不同步的问题&#xff0c;尤其是在高并发和异步环境下。本文将探讨双写一致性面临的主要问题和解决方案&#xff0c;重点关注最终一致性。 本文讨论的是最终一致性问题 双写一致性面…...

SUnet: A multi-organ segmentation network based on multiple attention【医学图像分割】

一、论文信息 1.1、中文名称 名称&#xff1a;SUnet&#xff1a;基于多重注意力的多器官分割网络 1.2、论文关键词 医学图像分割、Transformer、注意力机制、高效特征融合模块 1.3、核心概述 本文提出了一种新颖有效的医学图像分割方法 SUnet&#xff0c;用于腹部和胸部的多…...

uniapp实现“到这儿去”、拨打电话功能

"到这儿去" 在 UniApp 中实现“到这儿去”的功能,即调起地图导航至指定位置,对于不同的平台(小程序、H5、App)有不同的处理方式。下面将简单介绍如何在这些平台上实现该功能,并讨论位置信息的获取。后面需求会用到,先来找一些相关资料,并不一定很准确,但也来…...

2025年入职/转行网络安全,该如何规划?网络安全职业规划

网络安全是一个日益增长的行业&#xff0c;对于打算进入或转行进入该领域的人来说&#xff0c;制定一个清晰且系统的职业规划非常重要。2025年&#xff0c;网络安全领域将继续发展并面临新的挑战&#xff0c;包括不断变化的技术、法规要求以及日益复杂的威胁环境。以下是一个关…...

【博客之星】2024年度个人成长、强化学习算法领域总结

&#x1f4e2;在2025年初&#xff0c;非常荣幸能通过审核进入到《2024年度CSDN博客之星总评选》TOP300的年度评选中&#xff0c;排名40。这还是第一次来到这个阶段&#xff0c;作为一名博士研究生&#xff0c;还是备受鼓舞的。在这里我将以回顾的方式讲述一下这一年在CSDN中走过…...

HTML5 Canvas实现的跨年烟花源代码

以下是一份基于HTML5 Canvas实现的跨年烟花源代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">…...

使用通用预训练范式为 3D 基础模型铺平道路

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01;&#xff0c;本次是英文需要英文功底扎实的阅读。 Abstract In contrast to numerous NLP and 2D vision foundational models, learning a 3D foundational model poses considerably greater challenge…...

SpringMVC (2)

目录 1. RequestMapping 注解介绍 2. RequestMapping 使用 3. RequestMapping与请求方式 3.1 RequestMapping 支持Get和Post类型的请求 3.2 RequestMapping 指定接收某种请求 3.3 GetMapping和PostMapping 4. 传参 4.1 通过查询字符串传参 4.2 在 Body 中传参 4.2.1 …...

【Vim Masterclass 笔记16】S07L32 + L33:同步练习09 —— 掌握 Vim 宏操作的六个典型案例(含点评课内容)

文章目录 S07L32 Exercise 09 - Macros1 训练目标2 操作指令2.1. 打开 macros-practice.txt 文件2.2. 练习1&#xff1a;将旧版 Python 代码转换为新版写法2.3. 练习2&#xff1a;根据列表内容批量创建 Shell 脚本2.4. 练习3&#xff1a;对电话号码作格式化处理2.5. 练习4&…...

爬楼梯问题(Leetcode 第70题)

爬楼梯问题&#xff08;Leetcode 第70题&#xff09; 问题描述 假设你正在爬楼梯。每次你可以爬 1 个或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。…...

6.5 正定矩阵

一、正定矩阵 这一节关注的是特征值都是正数的对称矩阵。如果对称使得矩阵很重要&#xff0c;那么这个额外的性质&#xff08;所有的 λ > 0 \lambda>0 λ>0&#xff09;会使得它更加的特殊。我们所说的特殊并不表示它稀有&#xff0c;特征值都是正数的对称矩阵几乎…...

verilog笔记1

1. 阻塞赋值 阻塞赋值&#xff0c;顾名思义即在一个 always 块中&#xff0c;后面的语句会受到前语句的影响&#xff0c;具体来说就是在同一个always 中&#xff0c;一条阻塞赋值语句如果没有执行结束&#xff0c;那么该语句后面的语句就不能被执行&#xff0c;即被“阻塞”。也…...

游戏引擎学习第81天

仓库:https://gitee.com/mrxiao_com/2d_game_2 或许我们应该尝试在地面上添加一些绘图 在这段时间的工作中&#xff0c;讨论了如何改进地面渲染的问题。虽然之前并没有专注于渲染部分&#xff0c;因为当时主要的工作重心不在这里&#xff0c;但在实现过程中&#xff0c;发现地…...

git系列之revert回滚

1. Git 使用cherry-pick“摘樱桃” step 1&#xff1a; 本地切到远程分支&#xff0c;对齐要对齐的base分支&#xff0c;举例子 localmap git pull git reset --hard localmap 对应的commit idstep 2&#xff1a; 执行cherry-pick命令 git cherry-pick abc123这样就会将远程…...

监控与调试:性能优化的利器 — ShardingSphere

在分布式数据库系统中&#xff0c;监控和调试是确保系统高效运行的关键。ShardingSphere 提供了多种监控和调试工具&#xff0c;帮助开发者实时跟踪和优化性能&#xff0c;识别瓶颈&#xff0c;进行故障排查&#xff0c;从而提升系统的稳定性和响应速度。本文将介绍如何使用 Sh…...

LLVM - 编译器前端 - 理解BNF(巴科斯-诺尔范式)

一:概述 BNF(Backus-Naur Form,巴科斯-诺尔范式)是一种用于描述上下文无关文法的形式语言,广泛应用于定义编程语言、协议和文件格式的语法规则。 下面是一小段类Pascal编程语言,这个编程语言就可以用BNF描述。用BNF描述编程语言的语法规则之后,就可以根据这个规则生成抽…...

服务化架构 IM 系统之应用 MQ

在微服务化系统中&#xff0c;存在三个最核心的组件&#xff0c;分别是 RPC、注册中心和MQ。 在前面的两篇文章&#xff08;见《服务化架构 IM 系统之应用 RPC》和《服务化架构 IM 系统之应用注册中心》&#xff09;中&#xff0c;我们站在应用的视角分析了普适性的 RPC 和 注…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

CppCon 2015 学习:Time Programming Fundamentals

Civil Time 公历时间 特点&#xff1a; 共 6 个字段&#xff1a; Year&#xff08;年&#xff09;Month&#xff08;月&#xff09;Day&#xff08;日&#xff09;Hour&#xff08;小时&#xff09;Minute&#xff08;分钟&#xff09;Second&#xff08;秒&#xff09; 表示…...