费解的开关

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

我们用数字“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≤500

输入样例:

3
00111
01011
10001
11010
11100

11101
11101
11110
11111
11111

01111
11111
11111
11111
11111

输出样例:

3
2
-1


第一个方法(反向bfs) 反向暴力,从(1 << 25 - 1) 枚举6步之内可以到达的状态,用map记录状态和对应的次数。看输入的状态是不是在map中。这个方法,擦边超时。


#include<iostream>
#include<map>
#include<queue>
#define ll long long;
using namespace std;
map <long long, int>ans;int dx[5] = {0, -1, 1, 0, 0};
int dy[5] = {0, 0, 0, -1, 1};
long long scan() {string s;long long ans = 0;for (int i = 1; i <= 5; i++) {cin >> s;for (int j = 0; j < 5; j++) {ans = ans << 1;if (s[j] == '1') {ans = ans | 1;}}}return ans;
}
long long turn(long long s, int i) {long long  tem = s;int x = i / 5;int y = i % 5;for (int i = 0; i <= 4; i++) {int tx = x + dx[i];int ty = y + dy[i];if (tx < 0 || tx > 4 || ty < 0 || ty > 4) continue;int p = tx * 5 + ty;tem = (tem >> p & 1) ? (tem - (1 << p)) : (tem + (1 << p));}return tem;
}
void bfs() {queue<pair<long long, int > > que;que.push(make_pair((1 << 25) - 1, 0));ans[(1 << 25) - 1] = 0;while(!que.empty()) {long long s = que.front().first;int cnt = que.front().second;que.pop();if (cnt == 6) continue;for (int i = 0; i < 25; i++) {long long tem = turn(s, i);if (ans.find(tem) != ans.end()) continue;que.push(make_pair(tem, cnt + 1));ans[tem] = cnt + 1;}}
}
int main () {int n;cin >> n;bfs();while(n--) {long long s = scan();if (ans.find(s) == ans.end()) cout << -1 << "\n";else cout << ans[s] << "\n";}return 0;
}

第二个方法是利用了递推的思想,假设前面一行已经完全为1,如果在当前行出现0,就只能依靠下一行对应位置来改变。因为无论改变当前位置,还是改变左右的位置,都会打乱前一行的序列。

那问题的关键就是如何决策第一行。如果第一行出现了0,决策有3个,依靠改变左右和自己,和依靠改变下面。依靠下面的决策,我们可以放到递推的过程中。剩下的就是直接枚举依赖左右和自己的决策,即可。


#include<bits/stdc++.h>
using namespace std;
char tem[6][6];
char cp[6][6];
int dx[5] = {0, 0, 0 , -1 , 1};
int dy[5] = {0,1, -1, 0 , 0};
void turn(int x, int y) {for (int i = 0; i <= 4; i++) {int tx = x + dx[i];int ty = y + dy[i];if (tx < 1 || ty > 5 || ty < 1 || ty > 5) continue;tem[tx][ty] = tem[tx][ty] == '0' ? '1' : '0';}
}
int dp() {int ans = 10;for (int choice = 0; choice < (1 << 5); choice++) {memcpy(tem, cp, sizeof cp);int cnt = 0;for (int j = 0; j < 5; j++) {if ((choice >> j) & 1) {cnt++;turn(1, j + 1);}}for (int i = 1; i < 5; i++) {for (int j = 1; j <= 5; j++) {if (tem[i][j] == '0') {cnt++;turn(i + 1, j);}}}bool is_yes = true;for (int i = 1; i <= 5; i++) {if (tem[5][i] == '0') {is_yes = false;}}if (is_yes == true) ans = min(ans, cnt);}if (ans > 6) ans = -1;return ans;
}
int main () {int t;cin >> t;while (t--) {for (int i = 1; i <= 5; i++) {for (int j = 1; j <= 5; j++) {cin >> cp[i][j];}}cout << dp() << "\n";}return 0;
}

[递推] 费解的开关相关推荐

  1. 费解的开关(位运算+递推)

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

  2. C++费解的开关(递推,位运算)

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

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

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

  4. 0x02.基本算法 — 递推与递归

    目录 一.递推与递归 二.分治 三.模拟计算机实现递归 四.相应习题: 0.AcWing 92. 递归实现指数型枚举(递归/循环+位运算) 1.AcWing 93. 递归实现组合型枚举 2.AcWin ...

  5. 第一章:递推与递归 【完结】

    目前,这一章都已经熟练掌握了. 目录 92. 递归实现指数型枚举 [板子题] 94. 递归实现排列型枚举 [板子题] 93. 递归实现组合型枚举[板子题] 717. 简单斐波那契 [简单 / 递推] ...

  6. 蓝桥杯C++ AB组辅导课 第一讲 递归与递推 Acwing

    例题 AcWing 92. 递归实现指数型枚举 从 1∼n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案. 输入格式 输入一个整数 n. 输出格式 每行输出一种方案. 同一行内的数必须升序 ...

  7. 基本算法之递推与递归的简单应用

    递推与递归的简单应用 常见的枚举形式 实现指数型枚举 DFS (一) DFS (二) 位运算(一) 位运算(二) 实现组合型枚举 DFS + 剪枝 实现排列型枚举 DFS 费解的开关 奇怪的汉诺塔 分 ...

  8. 递归与递推类型题小结

    文章目录 1. 递归 1.1 解题思想 1.2 例题1(指数型枚举) 题意: 思路: 递归树模型: 时间复杂度: 代码实现: 1.3 例题2(排列型枚举) 题意: 思路: 递归树模型: 时间复杂度分析 ...

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

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

  10. AcWing 蓝桥杯AB组辅导课 01、递归与递推

    文章目录 前言 一.递归 知识点 例题 题目1:AcWing 95.斐波那契数列[简单,递归写法] 题目2:AcWing 92.递归实现指数型枚举[简单] 题目3:AcWing 94.递归实现排列型枚 ...

最新文章

  1. Qt for Android调用android原生控件安装apk
  2. linux 进程通信之 mmap
  3. 光栅图形学算法基础其二 (裁剪算法)
  4. jackson驼峰转下划线注解_jackson序列化与反序列化的应用实践
  5. 整理90部好看的经典喜剧片
  6. 打造具有物联网基因的现代化商业银行
  7. shell脚本ssh登录并执行命令_Linux批量免密码SSH登录案例
  8. Microsoft SQL Server 2008 安装图解(Windows 7)
  9. NLP学习(七)使用stanford实现句法分析-Python3实现
  10. react router 路由守卫_react实现路由守卫
  11. 我是一个大器晚成的投资人
  12. 【阿里云总监课】存储系统设计——NVMe SSD性能影响因素一探究竟
  13. java电话号码_java编程——电话号码查询系统
  14. 计算机图形学 实验6 直线的裁剪—Cohen Sutherland裁剪算法(MFC中)
  15. android 文件管理器下载,ES文件管理器下载
  16. Spring入门书籍
  17. html ol 序号不出来,html中ol标签不显示序号的解决办法
  18. Deepin Linux v20+安装微信3.1.2最新测试版的方法
  19. 组织QClub大连站活动的感受
  20. 2017关于计算机的知识,计算机基础知识及答案

热门文章

  1. 12306火车票查询
  2. SPIR-V 研究:编译器基本原理(三) - Chomsky文法分类
  3. IDEA自动生成 Author 注释 签名
  4. Linux性能优化之内存(一)
  5. 恒指赵鑫:04.11今日恒指早盘思路
  6. Process finished with exit code -1073740791 (0xC0000409)
  7. E-R图转化为关系模型
  8. c语言wakeup函数,关于RTC时钟RTC_Set_WakeUp(u32 wksel,u16 cnt)函数的疑惑
  9. 我用AI生成了这些明星一生的样貌变化 | 已填坑附源码
  10. 咻咻验证码,见证百合网发展壮大!