题面

一道非常好的递推练习题。

我们考虑每次枚举第一行的操作,由上一行的状态递推出下一行的状态,最后判断最后一行是否全部为 \(1\) 即可。

实现代码时要注意一些细节问题。

  1. #include <bits/stdc++.h>
  2. #define DEBUG fprintf(stderr, "Passing [%s] line %d\n", __FUNCTION__, __LINE__)
  3. #define itn int
  4. #define gI gi
  5. using namespace std;
  6. typedef long long LL;
  7. typedef pair <int, int> PII;
  8. typedef pair <int, PII> PIII;
  9. inline int gi()
  10. {
  11. int f = 1, x = 0; char c = getchar();
  12. while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
  13. while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  14. return f * x;
  15. }
  16. inline LL gl()
  17. {
  18. LL f = 1, x = 0; char c = getchar();
  19. while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
  20. while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  21. return f * x;
  22. }
  23. const int dx[] = {0, -1, 0, 1, 0}, dy[] = {0, 0, 1, 0, -1};
  24. //定义常量数组表示当前要翻转的灯及它上下左右的位置
  25. int n, m;
  26. char g[7][7];
  27. inline void get(int x, int y) //摁下第 x 行 y 列的灯
  28. {
  29. for (int i = 0; i < 5; i+=1) //将它本身及四周的灯翻转状态
  30. {
  31. int xx = x + dx[i], yy = y + dy[i];
  32. if (xx >= 0 && xx <= 4 && yy >= 0 && yy <= 4) //在界内
  33. {
  34. //进行翻转
  35. if (g[xx][yy] == '1') g[xx][yy] = '0';
  36. else g[xx][yy] = '1';
  37. }
  38. }
  39. }
  40. inline int getans() //求答案
  41. {
  42. int ans = 66666666;
  43. for (int k = 0; k < (1 << 5); k+=1) //枚举每一种第一行的操作状态
  44. {
  45. int sum = 0; //操作的总数
  46. char bf[7][7];
  47. memcpy(bf, g, sizeof g); //先将初始状态备份
  48. for (int j = 0; j < 5; j+=1)
  49. {
  50. if (k >> j & 1) //如果第 j 号灯需要翻转
  51. {
  52. ++sum; //操作一次
  53. get(0, j); //将第 j 号灯翻转
  54. }
  55. }
  56. for (int i = 0; i < 4; i+=1) //递推出下一行的状态
  57. {
  58. for (int j = 0; j < 5; j+=1) //枚举第 i 行的每一盏灯
  59. {
  60. if (g[i][j] == '0') //如果这个灯需要被翻转
  61. {
  62. ++sum;
  63. get(i + 1, j); //将它下一排的灯翻转
  64. }
  65. }
  66. }
  67. bool ok = true;
  68. for (int j = 0; j < 5; j+=1)
  69. {
  70. if (g[4][j] == '0') {ok = false; break;} //没有达到目标状态
  71. }
  72. if (ok) ans = min(ans, sum); //记录最少步数
  73. memcpy(g, bf, sizeof g); //还原备份
  74. }
  75. if (ans > 6) return -1; //不能在 6 步以内达到目标状态
  76. return ans; //返回答案
  77. }
  78. int main()
  79. {
  80. //freopen(".in", "r", stdin);
  81. //freopen(".out", "w", stdout);
  82. int t = gi(); //多组数据输入数据总数
  83. while (t--)
  84. {
  85. for (int i = 0; i < 5; i+=1) scanf("%s", g[i]); //输入每一行的状态
  86. printf("%d\n", getans()); //输出答案
  87. }
  88. return 0;
  89. }

题解【AcWing95】费解的开关的更多相关文章

  1. ACWing95. 费解的开关

    题解 这道题目有三个状态条件值得考虑: 每一个开关被按0次或者1次才有意义,如果超过1次,那么等同于按0或1次. 最终的结果与按的顺序无关 因为2,所以可以人为地规定比较合理的顺序. 现在以每一行为顺 ...

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

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

  3. TyvjP1266 费解的开关

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

  4. AcWing 95 费解的开关

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

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

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

  6. TVYJ1266:费解的开关

    我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:http://www.joyoi.cn/problem/tyvj-1266 这 ...

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

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

  8. 题解 P3870 【[TJOI2009]开关】/基础分块学习小结

    直接进入正题: 分块: 分块分块,就是把一个长串东西,分为许多块,这样,我们就可以在操作一个区间的时候,对于在区间里面完整的块,直接操作块,不完整的直接操作即可,因为不完整,再加上一个块本身就不大,复 ...

  9. 【ACwing 95】费解的开关——枚举 + 搜索

    (题面来自ACwing) 你玩过"拉灯"游戏吗?25盏灯排成一个5x5的方形.每一个灯都有一个开关,游戏者可以改变它的状态.每一步,游戏者可以改变某一个灯的状态.游戏者改变一个灯的 ...

随机推荐

  1. toj 3086 Passage (不错)

    Passage 时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte总提交: 40 测试通过: 20 描述 Bill is a millionaire. But ...

  2. js—数字那些事儿

    进制之间互相转化 a=133 十进制转成其他进制 a.toString(num) a.toString(2); //转化成二进制,返回"10000101" a.toString(8 ...

  3. C# protobuf自动更新cs文件

    网上的教程大都是手动通过protoc编译, 比较难用 给当前工程添加"Google.Protobuf"和"Grpc.Tools"的引用(通过nuget), 然后 ...

  4. Android中DatePicker日期选择器的使用和获取选择的年月日

    场景 实现效果如下 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 将布局改 ...

  5. 127.0.0.1 拒绝了我们的连接请求--访问本地IP时显示拒绝访问

    问题描述 今天在访问http://127.0.0.1时,浏览器显示"127.0.0.1 拒绝了我们的连接请求",需要设置浏览器设置 解决方法 1.打开控制面板,搜索"程序 ...

  6. Elasticsearch之增加和删除索引

    增加索引 利用postMan工具发送restfulAPI添加索引库 请求方式为put代表添加 创建索引index时映射mapping 请求URL: 使用put发送http://localhost:92 ...

  7. python基础入门之三 —— 字符串

    1.格式 一对引号和三对引号可以表示字符串 (三引号保留换行) 2.下标 从0开始循序向下分配 str1='abcdefg' print(str1) print(str1[0]) print(str1 ...

  8. 《手把手教你构建自己的 Linux 系统》学习笔记(9)

    目录 autoreconf 命令的作用是什么? aclocal automake -a autoconf 一条命令搞完三面三步 既然有其他的「编译控制软件」为何还是使用 make 来进行编译控制? M ...

  9. 基于90nm CMOS技术的功能齐全的64Mb DDR3 STT-MRAM

    自旋转矩磁阻随机存取存储器(ST-MRAM)有望成为一种快速,高密度的非易失性存储器,可以增强各种应用程序的性能,特别是在用作数据存储中的非易失性缓冲器时设备和系统.为此,everspin开发了基于9 ...

  10. 剑指offer-面试题50-第一个只出现一次的字符-哈希表

    /* 题目: 求字符串第一个只出现一次的字符. */ /* 思路: 使用map遍历两次,第一次计数,第二次找到计数为1的第一个字符. */ #include<iostream> #incl ...