(题面来自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. 2. DRF 认证、权限、限流、分页、过滤、序列 化

    2.1 user/urls.py   ModelViewSet注册路由三部曲 from django.urls import include, path from user import views ...

  2. 分四个阶段学习python并找到一份好工作

    第一阶段 关注公众号"轻松学编程"了解更多. 详细学习资料 需要时间一个月. 1.python概念 ​ python是一种解释型.面向对象.动态数据类型的高级程序语言. ​ 理解: ...

  3. scrapyd部署、使用Gerapy 分布式爬虫管理框架

    Scrapyd部署爬虫项目 GitHub:https://github.com/scrapy/scrapyd API 文档:http://scrapyd.readthedocs.io/en/stabl ...

  4. 跟我一起学.NetCore之EF Core 实战入门,一看就会

    前言 还记得当初学习数据库操作时,用ADO.NET一步一步地进行数据操作及查询,对于查询到的数据还得对其进行解析,然后封装返回给应用层:遇到这种重复而繁琐的工作,总有一些大神或团队对其进行封装,从而出 ...

  5. 区分部分javascript的选择器

    下面代码简单介绍一下js的选择器 <ul> <li id="li1">1</li> <li class="li2"&g ...

  6. iframe框架下的某一页面跳转到另外一个页面

    //iframe只在当前页跳转 window.location = "/Admin/Blog/Index"; 只在当前页跳转 而不是整个页面都跳转

  7. Doctrine\ORM\QueryBuilder 源码解析之 where

    背景 最近有需求实现类似于 QueryBuilder 的谓词语句,就去翻看了它的源码.先看两个例子 例子1 $qb = $em->createQueryBuilder(); $qb->se ...

  8. nginx&http 第六章 http 协议学习 1

    1.HTTP方法 GET :获取资源 ,GET 方法用来请求访问已被 URI 识别的资源 POST:传输(上传和下载)实体主体 ,POST 方法用来传输实体的主体.虽然用 GET 方法也可以传输实体的 ...

  9. vue 切换主题(换肤)功能

    一:先写好两个css样式放在static文件夹中 二:在index.html中添加css link链接 <link rel="stylesheet" id="sty ...

  10. Java的注释-标识符和关键字

    1.Java注释 单行注释 多行注释 文档注释 代码示例 public class Hello{    public static void main(String[] args) {         ...