目录

题目

思路

一、分析

二、如何枚举第一行操作?

三、turn(x,y)函数

四、结果

代码


题目

你玩过“拉灯”游戏吗?

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≤5000

输入样例:

3
00111
01011
10001
11010
1110011101
11101
11110
11111
1111101111
11111
11111
11111
11111

输出样例:

3
2
-1

思路

一、分析

  1. 开关按的顺序可以任意
  2. 每个开关最多按一次
  3. 由于第一行决定了第二行,第二行的按法是唯一确定的
  4. 以此类推,每一行开关的操作都由前一行灯的亮灭状态唯一确定
  5. 当操作到最后一行时,可以保证前n-1行全亮,再看最后一行,若最后一行不是全亮,则没有解决方案,否则有解决方案

二、如何枚举第一行操作?

  • 指数型枚举,可以写递归
  • 使用for循环来进行位运算枚举

5个数,每个数都取0/1,共有2^5=32种方案。

转换为二进制后发现,0~2^5-1(0~31)都能分别代表5个数排列组合形式,共32种。即二进制数是从00000B开始,到11111B结束

故可以用for(op=0;op<32;op++)来枚举32种方案,op代表0~31,即(00000B~11111B

注意这里的op代表着每一种方案,即告诉你哪盏灯该按,哪盏灯不该按;

        op从1~31,因为是位运算,所以是1~31的二进制和1的二进制从右向左进行与的操作,比如10100B的op,意思是第2、4位(右到左01234)需要按,不是代表灯有没有亮,32种状态其实是哪些灯要按,一种op对应一种固定的按法,所以是&1==1或者^1==0。(引自ACwing答疑评论区)

e.g. 01101B 代表着第1/3/4盏灯要按,所以如果判断出第0/2/3位数字为1的话,则说明需要按亮这三盏灯,二进制数是从右往左数,从第0位开始算的,而在使用turn函数时,i循环是从左往右开始,故turn(0,4-i)

判断第op种方案中的第k位数字是否是1?   op右移k位与1与运算 (op>>k&1)

三、turn(x,y)函数

turn(x,y),代表x行y列的坐标,该函数用于改变(x,y)坐标周围的灯的状态,需要使用dx,dy数组把周围的偏移量都记下来,分别记录本身+上下左右共五个坐标值,若超过了0或5边界,则直接忽略;然后与1进行异或^操作,取反

 如(x,y)格子:

左边为(x+1,y) ===(1,0)

右边为(x-1,y) ===(-1,0)

上 (x,y+1) ===(0,1)

下 (x,y-1) ===(0,-1)

把字符串中的0或1取反:与1做异或操作 (x^=1)

四、结果

第一行的32种操作方案中有32种最终按灯结果,有的没法让灯全亮,有的可以,所以在每次一种方案计算完成后,如果能让灯全亮,就都取这一次和上一次的min值,直到最后得出来的res就是32种方案里最小的按灯次数

代码

#include<bits/stdc++.h>
using namespace std;
const int N=6; ///字符串最后一位是'\0',因此要多定义一位
char g[N][N]; ///存方案
char backup[N][N];///存备份方案///数据偏移量,左、右、上、下、本身
int dx[5] = {-1, 0, 1, 0, 0}, dy[5] = {0, 1, 0, -1, 0};void turn(int x, int y){for (int i = 0; i < 5; i ++ ){int a = x + dx[i], b = y + dy[i];///(a,b)代表(x,y)周围的坐标if (a < 0 || a >= 5 || b < 0 || b >= 5) continue;/// 在边界外,直接忽略即可g[a][b] ^= 1; ///异或操作,将(a,b)取反}
}int main(){int t;cin>>t;while(t--){for(int i=0;i<5;i++)cin>>g[i]; ///输入初始状态的二维数组int res=7;///结果数for(int op=0;op<32;op++){  ///枚举第一行的32种方案memcpy(backup,g,sizeof g);int step=0;///按灯的步骤数for(int i=0;i<5;i++){if(op>>i&1){ ///如果第i位是1的话,按亮该盏灯step++;turn(0,4-i); ///二进制数的位数和for循环i开始的位数相反,所以用4-i代表需要打开的灯}}for(int i=0;i<4;i++){  ///第i行决定了第i+1行for(int j=0;j<5;j++){if(g[i][j]=='0'){ ///如果当前行的灯是灭的,///那必须要按亮下一行的灯,才能让它亮起来step++;turn(i+1,j);}}}bool dark = false;for(int i=0;i<5;i++){ ///判断最后一行的每盏灯的状态if(g[4][i]=='0'){dark=true;break;}}if(!dark) res=min(res,step); ///如果最后一行全亮,则得出结果数memcpy(g,backup,sizeof backup);///恢复g数组的状态}if(res>6) res=-1;cout<<res<<endl;        }return 0;
}

收获:

  1. memcpy函数的用法:memcpy(des,src,sizeof * );
  2. 位运算:右移x位后与1与运算,op>>x&1;异或运算,x与1异或运算是取反,x=x^1
  3. 坐标存储:取偏移量,类似棋盘问题,把上下左右即自身的偏移量放进两个数组里存起来,然后使用for循环来调用值
  4. 分析代码时,先按主干来分析,一步一步分析出自己需要什么变量,什么函数,函数可以最后完成

AcWing 95. 费解的开关 (yxc代码保姆级题解+注释)相关推荐

  1. AcWing 95. 费解的开关 Python详解

    一.算法思想--递推(详细证明见算法竞赛进阶指南原书) 1)若固定第1行,则方案至多只有1种 2)把第1行的所有情况遍历,先把亮着的灯全部关闭 3)遍历前4行,如果灯是关着的,就把下1行同1列的灯改变 ...

  2. AcWing 95. 费解的开关(指数型枚举)

    95. 费解的开关 题意: 给定一个5x5的方格,共25盏灯 每盏灯有开和关两种状态 每次操作一盏灯时,以该灯为中心的十字形状范围的灯都会改变状态 找到用最少的操作步数使所有的灯都亮着,当步数超过6时 ...

  3. 《算法竞赛进阶指南》打卡-基本算法-AcWing 95. 费解的开关:位运算、枚举、递推

    文章目录 题目解答 题目来源 题目解答 分析: 枚举第一行,指的是第一行哪些位置要切换状态!!!.第一行总共有5个数,组合数是32,即第一行哪些位置要切换总共有32种情况.这就是我们的枚举空间.比如, ...

  4. AcWing 95. 费解的开关

    原题链接:https://www.acwing.com/problem/content/97/ 看了前几篇题解和y总的视频讲解,总有一个奇怪的点搞不明白,为什么说第一行确定了,第二行就确定了,第三行接 ...

  5. Gitee上传代码保姆级教程(亲测有效)

    作为一名程序猿or程序媛,怎么能不会使用Gitee上传代码,协同开发呢? 今天,一个小白保姆级Gitee上传代码教程他来啦!亲测有效,小伙伴们来trytry吧! 前提 1.已经下载过Git Bash ...

  6. 【模型+代码/保姆级教程】使用Pytorch实现手写汉字识别

    前言 参考文章: 最初参考的两篇: [Pytorch]基于CNN手写汉字的识别 「Pytorch」CNN实现手写汉字识别(数据集制作,网络搭建,训练验证测试全部代码) 模型: EfficientNet ...

  7. 题解【acwing】95 费解的开关

    题目描述 点击进入题目 你玩过"拉灯"游戏吗?25盏灯排成一个5x5的方形.每一个灯都有一个开关,游戏者可以改变它的状态.每一步,游戏者可以改变某一个灯的状态.游戏者改变一个灯的状 ...

  8. Acwing:费解的开关

    题目描述 你玩过"拉灯"游戏吗? 25 盏灯排成一个 5×5 的方形. 每一个灯都有一个开关,游戏者可以改变它的状态. 每一步,游戏者可以改变某一个灯的状态. 游戏者改变一个灯的状 ...

  9. 95. 费解的开关【二级制枚举】

    二进制枚举第一行的操作状态. #include<bits/stdc++.h> using namespace std; const int N=30; char a[N][N],b[N][ ...

  10. 【JSP课程设计】个人信息管理系统(代码保姆级)

    目录 开发工具及开发环境 WEB系统注册与登录功能模块需求 1.1 注册功能 1.2 登录功能 登陆时的过程: 1.3 填写补充信息功能 1.3 查看注册信息功能 1.4 修改用户信息功能 1.5 用 ...

最新文章

  1. 拖着3个箱子,跨越太平洋,求学美帝 那一年我19岁
  2. 找出数组中任一重复的数字
  3. jmeter 计数器_JMeter函数
  4. flatten的用法
  5. SAP License:OAYZ中的使用年限无法更改
  6. Gremlin发布混沌工程实验平台免费版,开放了“故障即服务”功能
  7. adb shell 运行时报错“adb server version (26) doesn‘t match this client (39); killing...“的解决方案
  8. mysql 主从宕机切换_mysql主从复制配置操作以及主从宕机切换演练
  9. python文件拷贝到其他盘符_Python:文件操作技巧(File operation)
  10. ApiDoc 一键生成注释
  11. mysql where range_MYSQL explain详解之range
  12. 代码整洁之道 python_代码整洁之道的 7 个方法
  13. python播放全网视频+打包成exe
  14. 神舟微型计算机系统重装步骤,电脑重装系统步骤,最简单安全的操作!
  15. 达人评测 联想小新Pad Pro/Pad Plus怎么样
  16. Mongoose Populate
  17. 人脸识别相关资源大列表
  18. 简单的运动模糊效果实现
  19. 软件版本—— Alpha、Beta、RC版本的区别
  20. 为什么抖音张同学这么火爆?用 Python 分析 1w+条评论数据,我发现了其中的秘密

热门文章

  1. Win7下面安装VS2003
  2. 2020牛客多校九J-The Escape Plan of Groundhog
  3. SpringBoot接入Ueditor编辑器
  4. python火车票票价_python的requests库爬取火车票信息和所需价钱
  5. Snappy Installer
  6. [教程] PSP 5.00M33-6升级图文教程
  7. Capture web with FireShot
  8. 2018计算机专硕学硕,2018年考研要弄清学硕与专硕的区别
  9. mysql group by 配置_关于mysql group by 的设置
  10. 魔门云获得百万级天使轮投资,由创客100创投基金领投