9. 解谜游戏

目录

题目

Description

Input

Notes

思路

暴力方法

递归法

注意事项

C++代码(递归法)

关于DFS


题目

Description

小张是一个密室逃脱爱好者,在密室逃脱的游戏中,你需要解开一系列谜题最终拿到出门的密码。现在小张需要打开一个藏有线索的箱子,但箱子上有下图所示的密码锁。

每个点是一个按钮,每个按钮里面有一个小灯。如上图,红色代表灯亮,白色代表灯灭。每当按下按钮,此按钮的灯以及其上下左右四个方向按钮的灯状态会改变(如果原来灯亮则灯灭,如果原来灯灭则灯亮)。如果小张通过按按钮将灯全部熄灭则能可以打开箱子。

对于这个密码锁,我们可以先按下左上角的按钮,密码锁状态变为下图。

再按下右下角的按钮,密码锁状态变为下图。

最后按下中间的按钮,灯全部熄灭。

现在小张给你一些密码锁的状态,请你告诉他最少按几次按钮能够把灯全部熄灭。

Input

第一行两个整数

n,m(1 \leq n,m \leq 16 )

接下来

n

行,每行一个长度为

m

的01字符串,0表示灯初始状态灭,1表示灯初始状态亮。

Output

一行一个整数,表示最少按几次按钮可以把灯全部熄灭。

Notes

第一个样例见题目描述,第二个样例按左上和右下两个按钮。

测试用例保证一定有解

测试输入期待的输出时间限制内存限制额外进程
测试用例 1以文本方式显示
  1. 3 3↵
  2. 100↵
  3. 010↵
  4. 001↵
以文本方式显示
  1. 3↵
1秒64M0
测试用例 2以文本方式显示
  1. 2 3↵
  2. 111↵
  3. 111↵
以文本方式显示
  1. 2↵
1秒64M0

思路

暴力方法

对每个灯点或不点分情况讨论,共讨论2^(n*m)次,超时了。

递归法

核心是深度优先搜索(DFS)

1.用一个字符数组存各点的明暗情况,并且明确两点:

①一个灯至多按一次,按两次相当于没有按

②按的顺序对结果没有影响

2.如果第一排的点灯情况固定,那么后面n-1排的点灯情况也可固定;

因此我们可以枚举出第一排灯按与不按的所有情况,操作数为2^n;

自第二行开始到最后一行,通过判断上一行同一列的灯明灭与否来判断是否按灯;

最后需判断是否还有亮灯,如果有亮灯,则该枚举方法不合理;反之则记录点灯次数并与minPresses比较,更新minPresses值


注意事项

  • minPresses的初始值为n*m,因为每个灯至多按一次,n*m为按灯的最大次数
  • 用string来存取每一行的密码锁的状况,再遍历string将其存入二维数组
  • 改变按钮状态时,注意不要越界
  • 记得回溯。即在递归时,在按下当前按钮并进入下一次深搜后,要再次按下该按钮来复原。
  • 用cal函数计算时,传入数组,而不是传入数组的地址。因为传入地址后,按灯时会改变原数组的情况且无法复原,这样就会影响下一次的计算。(最后卡了好久就是因为这个)
  • 在递推完成之后要检验一下所有灯是否真的灭干净了,确认全部灯关掉之后再更新答案
  • 解法不唯一,应该枚举第一排灯按与不按的所有情况,不断更新minPresses


C++代码(递归法)

#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;//按下按钮的函数void pressButton(vector<vector<int>>&arr, int i, int j) {arr[i][j] = 1 - arr[i][j];//改变当前按钮的状态//改变上方按钮的状态if (i > 0) {arr[i - 1][j] = 1 - arr[i - 1][j];}//改变下方按钮的状态if (i < int(arr.size()) - 1) {arr[i + 1][j] = 1 - arr[i + 1][j];}//改变左方按钮的状态if (j > 0) {arr[i][j - 1] = 1 - arr[i][j - 1];}//改变右方按钮的状态if (j < int(arr[0].size()) - 1) {arr[i][j + 1] = 1 - arr[i][j + 1];}}//计算按下的总次数void cal(vector<vector<int>> arr, int curPresses, int& minPresses) {for (int i = 1; i < int(arr.size()); i++) {for (int j = 0; j <int(arr[0].size()); j++) {if (arr[i - 1][j] == 1) {pressButton(arr, i, j);curPresses++;}}}for (int i = 0; i < int(arr.size()); i++) {for (int j = 0; j <int(arr[0].size()); j++) {if (arr[i][j] == 1) return;}}minPresses = min(minPresses, curPresses); }// 递归遍历第一行密码锁按与不按的状态void traverseFirstRow(vector<vector<int>>& arr, int col, int curPresses, int& minPresses) {if (col == arr[0].size()) {cal(arr, curPresses, minPresses);return;}// 不按当前按钮traverseFirstRow(arr, col + 1, curPresses, minPresses);// 按当前按钮pressButton(arr, 0, col);traverseFirstRow(arr, col + 1, curPresses + 1, minPresses);pressButton(arr, 0, col); // 恢复按钮当前状态}int main() {int n, m;cin >> n >> m;int minPresses = n * m;vector<vector<int>> arr(n, vector<int>(m));//读取密码锁的状态for (int i = 0; i < n; i++) {string row;cin >> row;for (int j = 0; j < m; j++){arr[i][j]=row[j]-'0';}}traverseFirstRow(arr, 0, 0,minPresses);cout << minPresses << endl;return 0;}

关于DFS

DFS有一套固定的流程如下:

void dfs(状态参数){if (达到中止条件 / 条件不合法){添加相应内容return;}for (下一步所有的可行方法){标记;dfs(参数进行相应改变);还原标记;}}

对于本道题目,dfs部分的伪代码可以参考如下:

void dfs(灯的id, 按键次数){if (灯的id == m){根据第一行状态推演所有按键次数;判断所有灯是否全部熄灭;更新最小按键次数;return;}// 第一种:按下的情况按下(第一行,第id个灯);dfs(id + 1, 按键数 + 1);按下(第一行,第id个灯); // 还原灯的状态// 第二种:不按下的情况dfs(id + 1, 按键数);}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【Windows10】利用分区助手扩展C盘分区

文章目的&#xff1a;   在开始对C盘进行空间分配时&#xff0c;配额空间过小&#xff0c;后续使用希望扩展C盘的空间大小 分区助手百度网盘下载链接&#xff1a;link   提取码&#xff1a;go16 1、下载安装好分区助手后打开&#xff0c;点击右上角Tools&#xff0c;再点击…

将C盘分区部分容量分配给其他分区

最近在学习OpenStack相关的实验&#xff0c;硬盘容量需要分配一百多两百个G。电脑用久了&#xff0c;不知不觉磁盘也将要挤满的感觉&#xff0c;除C盘外。就想着把C盘的一些容量转到E盘里。 以下为具体步骤&#xff1a; 下载分区工具 选择合适的分区工具下载。我使用的是 win1…

Windows: 如何调整C盘分区大小

最开始安装系统&#xff0c;做分区时给C分区的大小一般都太小&#xff0c;后面发现不够时却无从下手。 Windows磁盘管理做不了这个事。因为它只能扩展后面为空白的。但D分区已有数据&#xff0c;无法扩展。 所以&#xff0c;我们得借助另一个工具&#xff1a;DiskGenius. 操…

【八股】2023秋招八股复习笔记5(计算机网络-CN)

文章目录 八股目录目录1、应用层 & HTTP一些http题HTTPS 加密原理&#xff08;问过&#xff09;HTTP/1.1 新特性HTTP/2.0 与 RPC&#xff08;问过&#xff09;GET 和 POST 比较 2、传输层 & TCPTCP三次握手 & 四次挥手&#xff08;问过&#xff09;为什么每次TCP 连…

基于vue和element的脚手架【vue-element-admin 和vue-element-plus-admin 】

vue-element-admin vue-element-admin 是一个后台前端解决方案&#xff0c;它基于 vue 和 element-ui实现 介绍 | vue-element-adminA magical vue adminhttps://panjiachen.github.io/vue-element-admin-site/zh/guide/ vue-element-plus-admin vue-element-plus-admin 是一…

keras深度学习框架通过简单神经网络实现手写数字识别

背景 keras深度学习框架&#xff0c;并不是一个独立的深度学习框架&#xff0c;它后台依赖tensorflow或者theano。大部分开发者应该使用的是tensorflow。keras可以很方便的像搭积木一样根据模型搭出我们需要的神经网络&#xff0c;然后进行编译&#xff0c;训练&#xff0c;测试…

脑优化全集

1电脑优化全集 一、系统优化设置 1、删除Windows强加的附件&#xff1a; a.用记事本NOTEPAD修改sysoc.inf&#xff08;在windiws/inf文件夹&#xff09;&#xff0c;用查找/替换功能&#xff0c;在查找框中输入,hide,7&#xff08;一个英文逗号紧跟hide&#xff0c;一个英文逗…

个人永久性免费-Excel催化剂功能第49波-标准数据结构表转报表样式结果

中国的企业信息化&#xff0c;已经过去了20年&#xff0c;企业里也产生了大量的数据&#xff0c;IT技术的信息化管理辅助企业经营管理也已经得到广泛地认同&#xff0c;现在就连一个小卖部都可以有收银系统这样的信息化管理介入。但同时也有一个很现实的问题&#xff0c;不是所…

个人永久性免费-Excel催化剂功能第37波-把Sqlserver的强大分析函数拿到Excel中用...

本人一直钟情于使用Sqlserver数据库的一大原因是其提供了非常好用、高效的数据分析函数&#xff08;窗口函数&#xff09;&#xff0c;可以在做数据清洗和数据分析场合等多个场景使用。只需简单的一个函数即可做出常规SQL语句很难以实现的效果。这么好用的函数&#xff0c;如今…

个人永久性免费-Excel催化剂功能第43波-文本处理类函数增强

Excel的函数有400多个&#xff0c;真正常用的50多个&#xff0c;而常有的文本处理类函数也不多&#xff0c;不是因为文本类处理简单&#xff0c;而是Excel真的有点挤牙膏式的每个版本更新那么几个小函数&#xff0c;普通用户等得急切&#xff0c;但实际上这些小函数&#xff0c…

个人永久性免费-Excel催化剂功能第30波-工作表快捷操作(批量创建、命名、排序、工作表目录)...

日常使用Excel过程中&#xff0c;最多的操作无外乎单元格和工作表的操作&#xff0c;单元格的操作在前面已经有详细的辅助功能提供&#xff0c;此篇提供工作表相关的操作。这两项的操作若能有提速&#xff0c;日常大量的工作叠加起来真是省下不少时间。 文章出处说明 原文在简书…

自定义镜像上传阿里云

目录 一、Docker制作jdk镜像 jdkv1.0版本 ① 编写Dockerfile文件 ② 执行Dockerfile文件&#xff0c;初次依赖镜像的时候会下载相应的镜像 ③ 查看镜像 ④ 创建并启动容器 二、alpine 制作jdk镜像 jdkv2.0的版本 1.alpine Linux 简介 2.基于 alpine 制作 j…

个人永久性免费-Excel催化剂功能第28波-工作薄瘦身,安全地减少非必要冗余

Excel催化剂在完善了数据分析场景的插件需求后&#xff0c;决定再补充一些日常绝大多数Excel用户同样可以使用到的小功能&#xff0c;欢迎小白入场&#xff0c;在不违背太多Excel最佳实践的前提下&#xff0c;Excel催化剂乐意为广大Excel用户们增添有价值和高频使用的快捷操作类…

计算机英语总结800,高三英语教师工作总结800字(通用5篇)

高三英语教师工作总结800字(通用5篇) 难忘的工作生活已经告一段落了&#xff0c;回顾这段时间的工作&#xff0c;相信你有很多感想吧&#xff0c;来为这一年的工作写一份工作总结吧。大家知道工作总结的格式吗&#xff1f;下面是小编精心整理的高三英语教师工作总结800字(通用5…

如何提高英语听力(内容摘自NECCS)+ 乘法表

乘法表 print(\n.join([ .join([%s*%s%-2s%(y,x,x*y) for y in range(1,x1)]) for x in range(1,10)])) 如何提高英语听力 很喜欢这篇关于提高英语听力的文章&#xff0c;所以收藏下来和大家一同分享一下 人走路时要用两条腿&#xff0c;没有任何人会觉得走路费劲。可如果让人…

张晓楠讲如何提高英语听力

张晓楠:现在是中央电视台财经频道&#xff08;CCTV-2&#xff09;的记者。曾任北京电视台青少频道主持人。原新浪网财经频道的主持人兼记者。毕业于美国哥伦比亚大学&#xff0c;主修金融方向&#xff0c;获公共管理硕士学位&#xff1b;曾在纽约摩根大通银行、瑞士信贷投资银行…

2023年6月GESP C++ 四级试卷解析

一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 1.高级语言编写的程序需要经过以下&#xff08; &#xff09;操作&#xff0c;可以生成在计算机上运行的可执行代码。 A.编辑 B.保存 C.调试 D.编译 【答案】D 【考纲知识点】编程环境(一级) 【解析】本题…

红警 1 游戏开源,代码非常规范,网友:秀色可餐

作者 | 程序员的那些事 来源 | 程序员的那些事&#xff08;id&#xff1a;iProgrammer&#xff09; 最后有一个小测试&#xff01;测测你是不是红警老玩家&#xff01; EA 部分开源红警啦&#xff01; 5 月 27 日&#xff0c;知名游戏公司 EA 在 GitHub 上搞了个大新闻&#xf…

《网络安全等级保护基本要求》(GB/T 22239-2019)标准解读

关键词: 等级保护对象; 安全通用要求; 安全扩展要求 中图分类号:TP309 文献标志码:A 文章编号:1671-1122&#xff08;2019&#xff09;02-0077-08 Baseline for Classified Protection of Cybersecurity (GB/T 22239-2019) Standard Interpretation MA Li1, ZHU Guobang2, L…

es学习记录

Elasticsearch 是一个实时的分布式搜索分析引擎&#xff0c;它被用作全文检索、结构化搜索、分析以及这三个功能的组合&#xff0c;内部使用 Lucene 做索引与搜索。 1.es的实际应用 2.es全文检索简单介绍 基础概念带过一下 Index 可类比为DBMS的库 Type 可类比一张表 Docu…