(题面来自ACwing)

你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。

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

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

输入格式

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

以下若干行数据分为n组,每组数据有5行,每行5个字符。每组数据描述了一个游戏的初始状态。各组数据间用一个空行分隔。

输出格式

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

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

  题意的本质是:求解把一个5 * 5的01方阵通过上述操作变换成为仅由1构成的方阵的最小步数。如果单纯每次枚举改变的点来爆搜,状态空间的大小不能承受,显然行不通。

  实际上,题中所给的变换具有两个很重要的性质。首先,每个点最多被变换一次,因为重复的操作是无效的;第二,相同操作的不同顺序不会影响最终结果,因为累计在每个位置上的效果都一样。

  从这两点出发,我们发现可以枚举部分变换来递推所有的操作。具体来说,考虑逐行进行变换,那么当前行i上面所有行所进行的变换已经确定了;如果第i-1行上的第k个位置上有0,那么只能通过改变第i行的第k个位置使第i-1行合法,这是解答本题的关键。因此,我们可以二进制枚举在第一行进行的2^5 = 32种变换,然后依次递推第2~5行的操作。最后检查第五行是否全部为1,若第五行状态合法就用当前的步数更新答案即可。

  从这个题吸取的教训是,要慎用语句"ios::sync_with_stdio(0)",因为这个指令取消了cin和C标准输入输出的兼容性,一旦手滑同时使用cin和getchar、scanf等C库读入函数就会发生错误。这句话最好在读入字符串时再考虑适用,平时应该手写快读来避免悲剧。

代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. #include <ctime>
  6. using namespace std;
  7. const int inf = 0x3f3f3f3f;
  8. int sw[10][10], tmp[10][10], cnt, ans;
  9. int addx[5] = {0, 0, 0, -1, 1}, addy[5] = {0, 1, -1, 0, 0};
  10. void change(int x, int y, int a[10][10]) {
  11. int tx, ty;
  12. for (int i = 0; i < 5; ++i) {
  13. tx = x + addx[i], ty = y + addy[i];
  14. if (a[tx][ty] == -1) continue;
  15. a[tx][ty] = !a[tx][ty];
  16. }
  17. ++cnt;
  18. }
  19. void init(int x) {
  20. memcpy(tmp, sw, sizeof(tmp));
  21. for (int i = 1; i <= 5; ++i)
  22. if (x >> (i - 1) & 1)
  23. change(1, i, tmp);
  24. }
  25. int main() {
  26. int T;
  27. cin >> T;
  28. while (T--) {
  29. ans = inf;
  30. memset(sw, -1, sizeof(sw));
  31. char ch;
  32. for (int i = 1; i <= 5; ++i) {
  33. while (!isdigit(ch))
  34. ch = getchar();
  35. for (int j = 1; j <= 5; ++j)
  36. sw[i][j] = ch - 48, ch = getchar();
  37. }
  38. /*      for (int i = 1; i <= 5; ++i) {
  39. for (int j = 1; j <= 5; ++j)
  40. cout << sw[i][j] << " ";
  41. cout << endl;
  42. }*/
  43. for (int x = 0; x < 32; ++x) {
  44. cnt = 0;
  45. init(x);
  46. for (int i = 2; i <= 5; ++i)
  47. for (int j = 1; j <= 5; ++j)
  48. if (!tmp[i - 1][j])
  49. change(i, j, tmp);
  50. for (int i = 1; i <= 5; ++i)
  51. if (!tmp[5][i]) cnt = inf;
  52. ans = min(ans, cnt);
  53. }
  54. if (ans <= 6)
  55. cout << ans << endl;
  56. else puts("-1");
  57. }
  58. return 0;
  59. }

【ACwing 95】费解的开关——枚举 + 搜索的更多相关文章

  1. AcWing 95 费解的开关

    目录 前言 题目链接 思路 代码 前言 博客咕咕咕了好久了,是时候写一下了 题目链接 AcWing 95 费解的开关 思路 首先可以看出 1.每一个位置顶多只会操作一次.因为如果操作两次的话,相当于不 ...

  2. ACWING 95 费解的开关 解题记录

    你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形.每一个灯都有一个开关,游戏者可以改变它的状态.每一步,游戏者可以改变某一个灯的状态.游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也 ...

  3. CH0201 费解的开关 枚举

    正解:枚举 解题报告: 入门傻逼题,思维难度不高代码量极小,非常适合上手 然后傻逼的我第二次看这道题的时候依然没想到解法:D 没有办法,就想着写个笔记好歹记录一下以后多复习几次就记着了趴qwq 就是, ...

  4. AcWing95. 费解的开关 枚举+位运算

    这道题的确比较难想,首先我们知道图比较小,有可能是枚举,那么该如何枚举呢??? 你可以发现,我们只要把第一排定了,并且保证第一排不准动,那么答案就定了 也就是说,我们首先用二进制枚举,枚举第一行需要翻 ...

  5. ACAG 0x02-4 费解的开关

    ACAG 0x02-4 费解的开关 对于这道题,我们不难发现如下性质: 每个位置之多被点击一次: 点击的先后顺序不影响结果: 若确定了第$1$行,则接下来可能的点击方案就只有$1$种.具体原因是:当第 ...

  6. TyvjP1266 费解的开关

    P1266 费解的开关 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述     你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形.每一个灯都有一个开关,游戏 ...

  7. hdu4431 Mahjong 枚举搜索。。

    japanese麻将什么玩意..都没有豪华七对... 没什么难的 就是枚举搜索了 分三种类型的胡牌 f1是七对 f2是十三幺 f3是普通的胡牌 就先找一对 再找三个三个的 就是一直超时..在峰峰的指导 ...

  8. AcWing 92. 递归实现指数型枚举

    题目链接:https://www.acwing.com/problem/content/description/94/ 题意:从 n 个数中选取数字,输出所有的选取可能 idea:枚举所有取数可能,就 ...

  9. HDU 4900 NO ACM NO LIFE(概率+枚举+搜索)(2014 Multi-University Training Contest 4)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4900 Problem Description There is an old country and ...

随机推荐

  1. Python ( 高级 第二部)

    目录 模块和包 面向对象 部分一: 面向对象程序开发 面向对象封装: 对象的相关操作 面向对象封装: 类的相关操作 实例化的对象/ 定义的类删除公有成员属性和公有成员方法 部分二: 单继承 多继承 菱 ...

  2. NB-IoT的RLC子层服务功能

    NB-IoT只支持RLC子层的确认模式(Acknowledgement Mode,AM),不支持非确认模式(Unacknowledged Mode,UM). 对于支持UP模式的UE,NB-IoT支持R ...

  3. python实现密码破解

    排列组合(破解密码) 关注公众号"轻松学编程"了解更多. 1.排列 itertools.permutations(iterable,n) 参数一:要排列的序列, 参数二:要选取的个 ...

  4. Git 2.20.1 安装及配置

    一.下载地址 https://git-scm.com/downloads   二.安装步骤1.windows 64bit1.1)双击 Git-2.20.1-64-bit.exe 安装 1.2)选择安装 ...

  5. P6773 [NOI2020]命运

    整体DP 很明显计算答案需要用容斥计算,如果暴力容斥的话,就是枚举哪些路径不符合条件,在这些路径的并集中的边都不能取,其他边任意取,设当前取了$i$条路径,那么对答案的贡献是$(-1)^i2^{n-1 ...

  6. Flink的sink实战之二:kafka

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. 一款基于.NET Core的认证授权解决方案-葫芦藤1.0开源啦

    背景 18年公司准备在技术上进行转型,而公司技术团队是互相独立的,新技术的推动阻力很大.我们需要找到一个切入点.公司的项目很多,而各个系统之间又不互通,导致每套系统都有一套登录体系,给员工和客户都带来 ...

  8. c#习题之3

    Dictionary<int, char> d = new Dictionary<int, char>(); int i=0; string s = "Welcome ...

  9. Elasticsearch 注册windows服务后,服务启动失败,意外终止

    直接双击elasticsearch.bat可以成功启动,注册成服务后就启动失败 从网上查找问题,发现是jdk版本的问题,用ES自带的jdk就可以启动成功. 默认ES会先找JAVA_HOME环境变量,如 ...

  10. Pytorch显存动态分配规律探索

    下面通过实验来探索Pytorch分配显存的方式. 实验 显存到主存 我使用VSCode的jupyter来进行实验,首先只导入pytorch,代码如下: import torch 打开任务管理器查看主存 ...