《算法竞赛·快冲300题》每日一题:“点灯游戏”

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

文章目录

  • 题目描述
  • 题解
  • C++代码
  • Java代码
  • Python代码

点灯游戏” ,链接: http://oj.ecustacm.cn/problem.php?id=1134

题目描述

【题目描述】 有一个n*n的灯泡矩阵,b表示灯暗,w表示灯亮。每个灯的位置上都有控制着这盏灯的按钮。当按下一个按钮后,该按钮以及周围位置(上下左右)的灯都会改变状态(亮->暗,暗->亮)。最少按下多少个按钮可以使得所有的灯都亮或者都暗。
【输入格式】 输入有多组数据,每组数据第一行有一个整数n(1≤n≤10),接下来n行,每行n个字符表示初始的灯泡矩阵。
【输出格式】 如果可以使得所有的灯泡都亮或者都暗,输出最少按下的按钮数目。如果无法达到,输出"Impossible"(不含引号) 。
【输入样例】

4
bwwb
bbwb
bwwb
bwww
4
bwbw
wwww
bbwb
bwwb

【输出样例】

4
Impossible

题解

   “点灯游戏”是一个经典问题,有多种解法。
  如果没有限制“最少按钮数”,只要求能实现全暗或全灭,如何操作?这里介绍一种被称为“首行穷举法”的方法,简单易行。设目标是把所有的灯变黑(暗),操作如下:
  (1)第一行不按动按钮,只需找到白灯的位置;
  (2)第二行对应第一行的白灯的位置,都是按钮,按下后,它上下左右的灯都变色,特别是上一行的白灯都会变黑,从而保证第一行都变成黑色;
  (3)每一行的按钮,都对应上一行的白灯,使上一行全变黑。
  本题要求得“最少按钮数”,可以把所有按钮都试一遍,找到最少的那种。为了减少尝试的次数,可以结合上述方法。本题的n≤10,规模很小,这种暴力法也可行。
  假设目标是最后都变成黑色,从第一行开始,逐行按动按钮。
  第一行有0000~1111共16种按按钮的方法。0000表示1个都不按,0001表示只按第1个按钮,0010表示只按第2个按钮,0011表示按第1、第2个按钮,…,等等。
  第一行选择一种方法按完之后,继续按动第二行。第二行如何按?显然要保证第一行都变成黑色才行。那么应该让第二行的按钮位置跟第一行的白色位置一样,因为第二行的按钮按动之后,它上面的白色会跟着变成黑色。
  按上述规则继续按后面的行,直到结束。
  下面举例说明。图中的“初态”是第一个样例的灯,黑表示暗,白表示亮。左上角坐标(0,0),右下角坐标(3,3)。
在这里插入图片描述
  (1)第一行的按钮设置。以第一行按0011为例,就是按第1、2个按钮。按第1个按钮(0,0)后得到图(1),再按第2个按钮(0,1)后得到图(2)。记录两个按钮的坐标(0,0)、(0,1)。
  (2)第二行的按钮设置。此时第一行只有第2个灯是白的,需要变成黑色。那么第二行必须按第2个按钮,才能让上面的白灯变成黑灯。第二行需要按的按钮的坐标是(1,1),得到图(3)的结果,第一行全黑了。
  (3)第三行的按钮设置。由于第二行全是黑的,所以第三行不用按了。
  (4)第四行的按钮设置。第三行的第3个灯是白的,需要变成黑色。那么第四行必须按第3个按钮,才能让上面的白灯变成黑灯。得到图(4)的结果,第三行全黑了。第四行需要按的按钮坐标是(3,2)。
  这四行结束后,第四行也变成了全黑,说明这是一次成功的操作,共按了4个按钮。
  第一行共有16种按钮设置方法,都按以上步骤操作一遍,其中按动按钮最少的就是结果全是黑灯的答案。
  以上假设最后都是黑色,也可以假设最后都是白色,再操作一次即可。取最少的按钮次数就是本题的答案。
  请读者按这个思路编码。下面的代码供参考。
【重点】 思维 。

C++代码

#include<bits/stdc++.h>
using namespace std;
char Map[11][11];
int n;
int GetBit(int x, int i){             //取出x的第i位return (x >> i) & 1;
}
void SetBit(int &x, int i, int v){        //将x的第i位设置成vif(v)  x |= (1 << i);else   x &= ~(1 << i);
}
void FlipBit(int &x, int i){         //将x的第i位取反x ^= (1 << i);
}
int solve(){int oriLights[11];    //灯的初态int Lights[11];       //按动按钮之后的灯的新状态int result[11];       //存需要按动的按钮int ans = n * n + 1;  //需要按动的按钮数不会大于n*nmemset(oriLights, 0, sizeof(oriLights));for(int i = 0; i < n; i++)           //把灯用二进制的位来表示,第i行,第j列for(int j = 0; j < n; j++){if(Map[i][j] == 'b')  SetBit(oriLights[i], j, 0);   //0表示暗else                  SetBit(oriLights[i], j, 1);   //1表示亮}for(int k = 0; k < (1<<n); k++)  {        //k是第0行的按钮,有0000~1111种按钮设置memcpy(Lights, oriLights, sizeof(oriLights)); int switchs = k;                      //第0行的按钮,例如k=0011,就是按第1、2个按钮for(int i = 0; i < n; i++) {          //逐一处理每行的灯result[i] = switchs;              //用result[i]记录第i行的按钮for(int j = 0; j < n; j++) {      //逐一处理每一列的灯if(GetBit(switchs, j)) {   if(j > 0)    FlipBit(Lights[i], j-1);  //j前面的第j-1灯变色FlipBit(Lights[i], j);                     //第j个灯变色if(j < n-1)  FlipBit(Lights[i], j+1);  //j后面的第j+1灯变色}}if(i < n-1)   Lights[i+1] ^= switchs;      //修改下一行的灯switchs = Lights[i];            //第i+1行按钮位置和第i行灯的位置相同}if(Lights[n-1] == 0) {            //最后一行也全变黑了,成功int tmp = 0;                    //tmp为开关矩阵中1的数目for(int i = 0; i < n; i++)      //(i,j)就是需要按动的按钮坐标for(int j = 0; j < n; j++)if(result[i] & (1<<j))tmp++;ans = min(ans, tmp);}}return ans;
}
int main(){while(scanf("%d", &n) != EOF)  {memset(Map, 0, sizeof(Map));for(int i = 0; i < n; i++)  scanf("%s", Map[i]);int ans = solve();                  //以全黑为目标做一次for(int i = 0; i < n; i++)          //反过来以全白为目标做一次for(int j = 0; j < n; j++)if(Map[i][j] == 'b')  Map[i][j] = 'w';else                  Map[i][j] = 'b';ans = min(ans, solve());if(ans > n * n)  puts("Impossible");else             printf("%d\n", ans);}return 0;
}

Java代码

import java.util.*;  
public class Main {  static int GetBit(int x, int i) {return (x >> i) & 1;}  static int SetBit(int x, int i, int v) {if (v == 1)   x |= (1 << i);else             x &= ~(1 << i);return x;}  static int FlipBit(int x, int i) {x ^= (1 << i);return x;}  static int solve(int n, String[] Map) {int[] oriLights = new int[n];for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {if (Map[i].charAt(j) == 'b')  oriLights[i] &= ~(1 << j);else        oriLights[i] |= (1 << j);}int ans = n * n + 1;for (int k = 0; k < (1 << n); k++) {int switchs = k;int[] Lights = oriLights.clone();int[] result = new int[n];for (int i = 0; i < n; i++) {result[i] = switchs;for (int j = 0; j < n; j++) {if (GetBit(switchs, j) == 1) {if (j > 0)   Lights[i] = FlipBit(Lights[i], j-1);Lights[i] = FlipBit(Lights[i], j);if (j < n-1) Lights[i] = FlipBit(Lights[i], j+1);}}if (i < n-1)      Lights[i+1] ^= switchs;switchs = Lights[i];}if (Lights[n-1] == 0) {int tmp = 0;for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if ((result[i] & (1 << j)) != 0) tmp++;ans = Math.min(ans, tmp);}}if (ans > n * n)     return -1;else             return ans;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while (scanner.hasNext()) {int n = scanner.nextInt();if (n == 0)  break; String[] Map = new String[n];for (int i = 0; i < n; i++)  Map[i] = scanner.next();int ans = solve(n, Map);// 循环遍历数组并替换字符for (int i = 0; i < n; i++) {Map[i] = Map[i].replace('b', 'x');  // 将'b'替换为临时字符'x'Map[i] = Map[i].replace('w', 'b');  // 将'w'替换为'b'Map[i] = Map[i].replace('x', 'w');  // 将临时字符'x'替换为'w'}ans = Math.min(ans, solve(n, Map));if (ans == -1)   System.out.println("Impossible");else             System.out.println(ans);}scanner.close();}
}

Python代码

  

 import sys
def GetBit(x, i):   return (x >> i) & 1def SetBit(x, i, v):if v:     x |= (1 << i)else:     x &= ~(1 << i)return xdef FlipBit(x, i):x ^= (1 << i)return xdef solve(n, Map):oriLights = [0] * nfor i in range(n):for j in range(n):if Map[i][j] == 'b':  oriLights[i]=SetBit(oriLights[i], j, 0) else:                 oriLights[i]=SetBit(oriLights[i], j, 1) ans = n * n + 1for k in range(1 << n):switchs = kLights = oriLights[:]result = [0] * nfor i in range(n):result[i] = switchsfor j in range(n):if GetBit(switchs, j):if j > 0:   Lights[i] = FlipBit(Lights[i], j-1)Lights[i] = FlipBit(Lights[i], j)if j < n-1: Lights[i] = FlipBit(Lights[i], j+1)if i < n-1:   Lights[i+1] ^= switchsswitchs = Lights[i]if Lights[-1] == 0:tmp = 0for i in range(n):for j in range(n):if result[i] & (1 << j):tmp += 1ans = min(ans, tmp)return ansfor line in sys.stdin:n = int(line.strip())if n == 0:  breakMap = []for i in range(n):   Map.append(input().strip())ans = solve(n, Map)F = {}F['b'] = 'w'F['w'] = 'b'for i in range(n):Map[i] = ''.join([F[x] for x in Map[i]])ans = min(ans,solve(n, Map))if ans > n * n:     print("Impossible")else:               print(ans)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/131986.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue cli 打包、生产环境http-proxy-middleware代理

结构树 版本 1、创建vue.config.js const path require(path); const UglifyJsPlugin require(uglifyjs-webpack-plugin) //压缩 const CompressionWebpackPlugin require(compression-webpack-plugin) const isProduction process.env.NODE_ENV ! development;module.exp…

请求与响应以及REST风格

目录 请求与响应请求参数参数传递 五种类型参数传递普通参数POJO数据类型嵌套POJO类型参数数组类型参数集合类型参数 JSON数据传输参数JSON普通数组JSON对象数据JSON对象数组知识点1&#xff1a;EnableWebMvc知识点2&#xff1a;RequestBodyRequestBody与RequestParam区别日期类…

[SICTF 2023] webmisc

文章目录 webBaby_PHP涉及知识点 我全都要RCE你能跟得上我的speed吗 miscPixel_art攻破这个压缩包&#xff01; web Baby_PHP 涉及知识点 php解析特性apache换行解析漏洞无参RCE 源代码 <?php highlight_file(__FILE__); error_reporting(0);$query $_SERVER[QUERY_ST…

OpenCV Series : Target Box Outline Border

角点 P1 (255, 000, 000) P2 (000, 255, 000) P3 (000, 000, 255) P4 (000, 000, 000)垂直矩形框 rect cv2.minAreaRect(cnt)targetColor roi_colortargetThickness 1targetColor (255, 255, 255)if lineVerbose:if True:cv2.line(ph…

做机器视觉工程师,其实挺没意思的

3.康耐视VisionPro高级脚本系列教程-3.脚本编辑错误和运行错误调试方法&#xff0c;break和Contitinuee的差别_哔哩哔哩_bilibili 其实人生就是“有时有意思&#xff0c;有时没意思”。 心里有太多的不甘心&#xff0c;太多的苦水&#xff0c;是没法再吃学习的苦&#xff0c…

市场调查中的信度和效度分析原理及python实现示例

市场调查中的信度和效度分析 1.量表信度分析1.1 内部一致性信度&#xff1a;克朗巴赫α系数原理1.2 python实现示例 2.量表效度分析2.1 内容效度2.1.1 原理2.1.2 python实现示例 2.2 准则效度2.2.1 原理2.2.2 python实现示例 2.3 结构效度2.3.1 原理2.3.2 python实现示例 3.量表…

[PyTorch][chapter 54][GAN- 1]

前言&#xff1a; GAN playground: Experiment with Generative Adversarial Networks in your browser 生成对抗网络&#xff08;Generative Adversarial Nets&#xff0c;GAN&#xff09;是一种基于对抗学习的深度生成模型&#xff0c;最早由Ian Goodfellow于2014年在《Gener…

selenium.chrome怎么写扩展拦截或转发请求?

Selenium WebDriver 是一组开源 API&#xff0c;用于自动测试 Web 应用程序&#xff0c;利用它可以通过代码来控制chrome浏览器&#xff01; 有时候我们需要mock接口的返回&#xff0c;或者拦截和转发请求&#xff0c;今天就来实现这个功能。 代码已开源&#xff1a; https:/…

使用java连接Libvirtd

基于springboot web 一、依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId>&l…

用c语言编写出三底模型

以下是一个用C语言实现三底模型的示例代码。这个程序通过循环遍历输入的股票数据&#xff0c;判断是否出现三底形态&#xff0c;如果是&#xff0c;则输出买入信号&#xff0c;否则输出卖出信号。 c语言 #include <stdio.h> #include <stdlib.h> // 判断是否出现…

Java项目---图片服务器

图片服务器--->服务器&#xff08;图床&#xff09; 核心功能&#xff1a;上传图片、展示图片等 比如&#xff1a;编写博客时我们会插入图片&#xff0c;本质上是往文章中放了一个链接&#xff08;URL&#xff09;&#xff0c;这个URL资源在另外一个服务器上。 核心知识点…

FPGA 纯VHDL解码 IMX214 MIPI 视频,2路视频拼接输出,提供vivado工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 MIPI 编解码方案3、本 MIPI CSI2 模块性能及其优越性4、详细设计方案设计原理框图IMX214 摄像头及其配置D-PHY 模块CSI-2-RX 模块Bayer转RGB模块伽马矫正模块VDMA图像缓存Video Scaler 图像缓存HDMI输出 5、vivado工程详解PL端FPGA硬件设…

无涯教程-JavaScript - INFO函数

描述 INFO函数返回有关当前操作环境的信息。 语法 INFO (type_text) 争论 Argument描述Required/OptionalType_text 指定要返回的信息类型的文本。 下表给出了Type_text的值和相应的返回信息。 Required Type_text 返回的信息"目录" 当前目录或文件夹的路径。&qu…

【Proteus仿真】【STM32单片机】四驱寻迹避障小车

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 系统运行后&#xff0c;LCD1602显示红外、超声波检测状态和距离、小车运行状态。可通过K1键可手动切换模式&#xff0c;寻迹、避障、蓝牙遥控&#xff1b;也可通过蓝牙发送指令切换模式&#xff1b; 当处…

系统架构设计之道,论如何构建一个资金账户系统

&#x1f449;导读 资金账户是互联网和金融业务中非常常见的系统&#xff0c;尤其是在电商、支付等业务中必不可少。资金账户系统本身其核心模块的整体架构往往并不复杂&#xff0c;但其对于资金安全和可用性的要求非常高&#xff0c;导致建设好一个资金账户系统并不容易。本文…

【Spring Boot】有这一文就够了

作者简介 前言 作者之前写过一个Spring Boot的系列&#xff0c;包含自动装配原理、MVC、安全、监控、集成数据库、集成Redis、日志、定时任务、异步任务等内容&#xff0c;本文将会一文拉通来总结这所有内容&#xff0c;不骗人&#xff0c;一文快速入门Spring Boot。 专栏地址…

MySQL安装validate_password_policy插件

功能介绍 validate_password_policy 是插件用于验证密码强度的策略。该参数可以设定三种级别&#xff1a;0代表低&#xff0c;1代表中&#xff0c;2代表高。 validate_password_policy 主要影响密码的强度检查级别&#xff1a; 0/LOW&#xff1a;只检查密码长度。 1/MEDIUM&am…

YashanDB:潜心实干,数据库核心技术突破没有捷径可走

都说数据库是三大基础软件中的一块硬骨头&#xff0c;技术门槛高、研发周期长、工程要求高&#xff0c;市场长期被几大巨头所把持。 因此&#xff0c;实现突破一直是中国数据库产业的夙愿。自上个世纪80年代起&#xff0c;中国数据库产业走过艰辛坎坷的四十余载&#xff0c;终…

vue组件库开发,webpack打包,发布npm

做一个像elment-ui一样的vue组件库 那多好啊&#xff01;这是我前几年就想做的 但webpack真的太难用&#xff0c;也许是我功力不够 今天看到一个视频&#xff0c;早上6-13点&#xff0c;终于实现了&#xff0c;呜呜 感谢视频的分享-来龙去脉-大家可以看这个视频&#xff1a;htt…

美东一公司的郁闷面试题

说是题目可以用不同的语言&#xff0c;但是貌似 Java 是多线程的&#xff0c;用 Java 写肯定容易不少。 但&#xff0c;觉得这个题目用多线程简直是有点脱了裤子放屁。 完整题目内容 题目的网站内容如下&#xff1a; Please complete the following challenge in one of th…