朝题夕解之以递推为背景的开关问题(一)

简介: 朝题夕解之以递推为背景的开关问题(一)

题目描述

微信图片_20221018151841.jpg解题报告


一、题意理解

游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。

使用windows自带的画图,摁住shift拖动鼠标画出下列的图形进行演示。

微信图片_20221018151936.png

样例演示:

微信图片_20221018152001.png

二、每一行开关的操作完全由前一行灯的亮灭决定


  1. 假设第一行的所有状态用枚举来确定,每个开关要么摁,要么不摁,在这里就是2 5 2^52 5 次种选法。
  2. 依次依据前一行的亮灭状态,决定它的下一行可以怎么摁,才能保证这个前一行是亮的。


/

微信图片_20221018152046.jpg

三、细节敲定


1.如何枚举第一行的32中操作。一个五位二进制正好可以表示这32种操作。比如

11010 => 对应第26个操作。那么0 ~ 2 5 2^52 5-1就可以逐一对应枚举第一行会有的32种方案


2.开关点亮函数

点击一个位置的开关以后,它上下左右四个位置的开关都会被改变状态。用四个i f ifif就显得太麻烦了。这里考虑的是通过添加偏移量实现。

微信图片_20221018152250.jpg

3.时间复杂度

32 ∗ 25 ∗ 5 ∗ 500 = 2000000 32 * 25 * 5 * 500 = 200000032∗25∗5∗500=2000000,大概是两百万次的运算。是完全没有问题的


参考代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 6;
char g[N][N],backup[N][N];
int dx[] = {-1,0,1,0,0} , dy[] = {0,-1,0,1,0};
//补全turn 函数
void turn(int x,int y)
{
    for(int i = 0; i < 5;i++)
    {
        int a = x+dx[i] , b = y + dy[i];
        //判断边界
        if(a < 0 || a >= 5 || b < 0 || b>= 5) continue;
        //更新状态
        g[a][b] ^= 1;
    }
}
int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        //构建地图
        for(int i = 0; i < 5;i++) cin >> g[i];
        int res = 10;//记录答案
        //枚举第一行的32种选择
        for(int op = 0; op < 32;op++)
        {
            memcpy(backup,g,sizeof g);
            int step = 0;//记录执行的步骤
            //处理当前这个方案是否有可以摁亮的灯
            for(int i = 0; i < 5; i++)
            {
                if(!(op >> i &1))
                {
                    step ++;
                    turn(0,i);
                }
            }
            //根据第一行现在的情况,处理后面四行的处理情况
            for(int i = 0; i < 4;i++)
            {
                for(int j = 0; j < 5;j++)
                if(g[i][j] == '0') 
                {
                    step ++;
                    turn(i+1,j);
                }
            }
            //遍历最后一行,倘若有黑的灯,那么当前方案失败
             bool dark = false;//标记
            for(int i = 0; i < 5;i++)
                if(g[4][i] == '0')
                {
                    dark = true;
                    break;
                }
            if(!dark) res = min(res,step);
            memcpy(g,backup,sizeof g);//从备份中把数据拿回来
        }
            if(res > 6) res = -1;//res = -1代表无解
            cout << res << endl;
    }
    return 0;
}


相关文章
|
7月前
|
存储 关系型数据库 分布式数据库
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
502 7
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
12月前
|
负载均衡 算法 Linux
深入探索Linux内核调度器:公平与效率的平衡####
本文通过剖析Linux内核调度器的工作机制,揭示了其在多任务处理环境中如何实现时间片轮转、优先级调整及完全公平调度算法(CFS),以达到既公平又高效地分配CPU资源的目标。通过对比FIFO和RR等传统调度策略,本文展示了Linux调度器如何在复杂的计算场景下优化性能,为系统设计师和开发者提供了宝贵的设计思路。 ####
279 26
|
并行计算 编译器 异构计算
vcpkg install libtorch[cuda] -allow-unsupported-compiler
vcpkg install libtorch[cuda] -allow-unsupported-compiler
259 2
|
存储 编译器 C语言
【C++】C++中规范[ 类型转换标准 ] 的四种形式
【C++】C++中规范[ 类型转换标准 ] 的四种形式
|
编译器 C语言 C++
【C++成长记】C++入门 | 类和对象(上) |面向过程和面向对象初步认识、类的引入、类的定义、类的访问限定符及封装
【C++成长记】C++入门 | 类和对象(上) |面向过程和面向对象初步认识、类的引入、类的定义、类的访问限定符及封装
Wordpress 站点健康-缺少一个或多个推荐的模组
Wordpress 站点健康-缺少一个或多个推荐的模组
|
JavaScript 前端开发 数据可视化
WebGL:基于web的交互式2D/3D图形引擎
WebGL(Web图形库)是一个JavaScript应用程序编程接口(API),用于实现交互式Web图形。
595 0
|
SQL 弹性计算 分布式计算
使用EMR+DLF+OSS-HDFS进行数据湖分析
本实验通过使用EMR,搭建EMR集群,对OSS-HDFS进行数据湖分析
|
Java API 开发者
如何触发Thread.sleep抛出的InterruptedException?
其实说来也简单,就是Thread.sleep所在的线程被interrupt了就抛出InterruptedException,但由于历史遗留问题这个十分罕见的情况变成了所有开发者都需要处理的常情,从这个细节的设计可以看出Thread这个类的历史遗留相当严重,其实java早已无法完全兼容旧版本,删除废弃了很多API,但仍然无法改良这些关键部分的设计。
649 0