AcWing95.费解的开关

2023-11-03 00:15
文章标签 开关 acwing95 费解

本文主要是介绍AcWing95.费解的开关,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目

你玩过“拉灯”游戏吗?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 ≤ 500 0<n≤500 0<n500

输入样例

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

输出样例

3
2
-1

思路

很容易发现三个性质:

  1. 每个位置至多只会被点击一次。
  2. 若固定了第 0 行(不能再改变第 0 行),则满足题意的点击方案至多只有1种。原因是:当第 i i i 行某一位为 0 时,若前 i i i 行已被固定,只能点击第 i + 1 i+1 i+1 行该位置上的数字才能使第 i i i 行的这一位变成1。从上到下按行使用归纳法可得上述结论。
  3. 点击的先后顺序不影响最终结果。

于是,不妨先考虑第 0 行如何点击【因为如果不改变当前第 0 行的状态,得到的结果可能并不是最优解】。在枚举第 0 行的点击方法( 2 5 = 32 2^5 = 32 25=32 种)后,就可以认为第 0 行 “固定不变”,再考虑第 1 ~ 4 行如何点击。 而按照上述性质2,此时的第 1 ~ 4 行的点击方案是确定的——从第 0 行开始递推,当第 i i i 行某一位为 0 时,点击第 i + 1 i+1 i+1 行该位置上的数字。若到达第 n − 1 n - 1 n1 行时不全为 1 【第 n − 1 n - 1 n1 行已经为最后一行,状态不能再修改了】,说明这种点击方式不合法。在所有合法的点击方式中取点击次数最少的就是答案。对第 0 行的 32 次枚举涵盖了该问题的整个状态空间,因此该做法是正确的。

对于第一行点击方法的枚举,可以采用位运算的方式,枚举0 ~ 31 这 32 个 5 位二进制数,若二进制数的第 k ( 0 ≤ k < 5 ) k(0 \le k \lt 5) k0k<5 位为1,就点击该矩阵第 0 行第 k k k 列的数字。

代码

#include<bits/stdc++.h>
using namespace std;const int INF = 1000000;
const int N = 5;
char matrix[N][N];//某个位置的灯状态被修改,则一共有5个位置的灯状态发生改变(上下左右中)
int dx[5] = {0, -1, 1, 0, 0}, dy[5] = {0, 0, 0, -1, 1};//修改(x,y)位置的灯的状态
void turn(int x, int y) {//(x,y) 位置上的状态发生改变,则要同步修改(a,b)位置上的状态for (int i = 0; i < 5; i++) {int a = x + dx[i];int b = y + dy[i];if (a >= 0 && a < 5 && b >= 0 && b < 5) { //判断位置是否合法matrix[a][b] ^= 1; //修改(a,b)位置的状态,如果原先是0就变为1,原先是1就变为0}}
}int work() {int ans = INF;//枚举第0行的状态(所有状态的编码为k)//第j位为1表示在第j位进行了一次操作 for (int k = 0; k < (1 << 5); k++) {int step = 0;char backup[N][N];memcpy(backup, matrix, sizeof(matrix)); //matrix复制一份放到backup中for (int j = 0; j < 5; j++) {if ((k >> j) & 1) {//如果是1,表示要第j位要按一下step++;turn(0, j);}}//第0行的状态已经固定//开始递推前四行的状态//用第i行的状态确定第i+1行的状态for (int i = 0; i < 4; i++) { //推到倒数第二行for (int j = 0; j < 5; j++) {if (matrix[i][j] == '0') { //将同列的下一个位置修改step++;turn(i + 1, j);}}}//判断最后一行是否全部为1bool successful = true;for (int j = 0; j < 5; j++) {if (matrix[4][j] == '0') {successful = false;break;}}if (successful) ans = min(ans, step);memcpy(matrix, backup, sizeof(backup)); //矩阵恢复原状}if (ans > 6) ans = -1;return ans;
}int main() {int n;cin >> n;while (n--) {for (int i = 0; i < 5; i++)cin >> matrix[i];cout << work() << endl;}return 0;
}

这篇关于AcWing95.费解的开关的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/334265

相关文章

Android Switch开关

Switch相关XML 属性 android:checked="true"android:thumb="@drawable/alert_dialog_icon" //开关android:track="@drawable/img1" //开关滑动轨道android:textStyle="bold"android:typeface="monospace"android:switchM

Android ToggleButton 开关按钮

ToggleButton相关属性,方法android:textOn="On"android:textOff="Off"android:checked="true"setChecked(boolean) package shortcut.song.com.myapplication;import android.support.v7.app.AppCompatActivity;impo

100盏灯开关问题

问题描述: 有100盏灯泡,第一轮点亮所有电灯,第二轮每两盏灯熄灭一盏,即熄灭第2盏,第4盏,以此类推,第三轮改变编号为3的倍数的电灯,第3盏,第6盏,如果原来那盏灯是亮的,就熄灭它,如果原来是灭的,就点亮它,以此类推,直到第100轮。问第100结束后,还有多少盏灯泡是亮的? 解答: 分析可知如果最后某一盏灯是亮着的,那么它一定是被切换了奇数次(第0次的时候全部都关着)。

Android 之 电灯泡开关效果

<?xml version="1.0" encoding="utf-8"?>   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:orientation="vertical"      android:layout_width="fill_parent

OpenCV利用滑动条实现一个开关

//-----------------------------------------------------------------------// 代码说明:以下代码来自Learning OpenCV官方源码// 注:改代码并没有添加图片,仅是实现了开关的窗口实现,// switch_off_function与switch_on_function方便外部看开关功能的

自定义控件 - swicth开关,仿ios的UISwitch

转载请标明出处: http://blog.csdn.net/u013254166/article/details/79161247 本文出自: 【rhino博客】  直接上效果图,实现很简单,这里就不赘述了。 最后附上源码下载链接,点击下载。

开关二极管损坏如何判断

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言1. 外观检查2. 测量正向压降3. 反向电阻测量4. 电路功能测试5. 高压测试6. 加热测试 前言 送给大学毕业后找不到奋斗方向的你(每周不定时更新) 中国计算机技

音频检测电路 | 声音传感器模块 | 口哨开关 | Arduino

音频检测电路 | 声音传感器模块 | 口哨开关 | Arduino 案例分析电路设计1. **基本音频检测电路设计**电路结构:2. **灵敏度调节原理**方法:3. **非 MCU 控制的 LED 触发**设计步骤:4. **电路示例**5. **示意图(文本描述)**总结 实验方法 案例分析 一个硅胶娃娃,挤压或拍打会亮灯; 这个硅胶玩偶的工作原理可能是基于以下几个

晶体管 开关|放大电路

文章目录 三极管(双极型晶体管 BJT)NPN与PNP几种区分方法三极管放大的物理原理三极管的两端是一样的吗? 为什么一个叫集极一个叫发射极三极管实验 mos管三级管和mos管的区别 三极管(双极型晶体管 BJT) 三极管是一种控制电流的半导体器件 (控制元件) 两种BJT类型 三极管在数模电路的体现与应用 NPN与PNP几种区分方法 看箭头:NPN(P型)的箭头