Vijos1197 费解的开关 枚举+位运算
题目
你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
我们用数字“1”表示一盏开着的灯,用数字“0”表示关着的灯。下面这种状态
10111
01101
10111
10000
11011
在改变了最左上角的灯的状态后将变成:
01111
11101
10111
10000
11011
再改变它正中间的灯后状态将变成:
01111
11001
11001
10100
11011
给定一些游戏的初始状态,编写程序判断游戏者是否可能在6步以内使所有的灯都变亮。
题解
取出整数n在二进制表示下的第k位 (n>>k)&1
把整数n在二进制表示下的第k位取反 n xor (1<< k)
正确的做法有很多种,我用的是其中一种
根据题解:
在上述规则的01矩阵的点击游戏中,很容易发现两个性质:
1.每个位置至多只会被点一次
2.若固定了第一行(不能再对第一行进行操作),则满足题意的点击方案至多只有1种。其原因是当第i行某一位为1时,若前i行已被固定,只能点击第i+1行该位置上的数字才能使第i行的这一位变成0.从上到下按行使用归纳法可得上述结论。
于是,我们可以枚举第一行的点击方法,共2^5=32种。完成第一行的点击后,固定第一行,按照上述性质2从第一行开始递推。若到达第n行不全为1则说明这种点击方式不合法。在所有合法的点击方式中取点击次数最少的就是答案。对第一行的32次枚举涵盖了该问题的所有可能状态,因此该做法是正确的。
对于第一行点击方式的枚举可以采用位运算或递归的方式
位运算方式:枚举0—31这32个5位二进制数,若二进制的第k位为1,就点击第一行第k+1列的数字
代码
#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;const int c[8]={1,2,4,8,16,32,64};
int n,ans;
int a[8],b[8];
char ch[8];void change(int i,int j){j--;a[i]^=1<<j; if (j+1<5) a[i]^=1<<(j+1);if (j-1>=0) a[i]^=1<<(j-1);a[i+1]^=1<<j;a[i-1]^=1<<j;
}int work(){int cnt=0;for (int i=2;i<=5;i++){for (int j=1;j<=5;j++)if (!((a[i-1]>>(j-1))&1)) change(i,j),cnt++;}if (a[5]==31) return cnt;return 1000000;
}void first(int k,int s){if (k>=5){memcpy(b,a,sizeof(b));int kk=s+work();memcpy(a,b,sizeof(a));ans=min(kk,ans);return;}for (int i=k+1;i<=5;i++){change(1,i);first(k+1,s+1);change(1,i); }first(k+1,s);
}int main(){scanf("%d",&n);for (;n;n--){memset(a,0,sizeof(a));for (int i=1;i<=5;i++){scanf("%s",ch);for (int j=4;j>=0;j--)if (ch[j]=='1') a[i]+=c[4-j];}ans=100000;first(0,0);if (ans<=6) printf("%d\n",ans); else printf("-1\n");}
}
Vijos1197 费解的开关 枚举+位运算相关推荐
- 费解的开关(位运算+递推)
题目描述: 你玩过"拉灯"游戏吗?25盏灯排成一个5x5的方形.每一个灯都有一个开关,游戏者可以改变它的状态.每一步,游戏者可以改变某一个灯的状态.游戏者改变一个灯的状态会产生连锁 ...
- c语言 枚举,位运算
c语言 枚举,位运算 枚举 枚举类型的定义和枚举变量的说明 一.枚举的定义枚举类型定义的一般形式为 二.枚举变量的说明 枚举类型变量的赋值和使用 位运算 位域 一.位域的定义和位域变量的说明 二.位域 ...
- 蓝桥备赛第一周2021.1.11 递归 枚举 位运算
文章目录 递归实现指数型枚举 递归指数型枚举 方法1:肯定是2^n行,所以直接就是上一个动态m从0到n加一堆空行 方法2:以最新的值为n为结束,遇到为0的不输出,用完要恢复为0 递归实现排列型枚举 非 ...
- vijos1197-费解的开关【递推,枚举,位运算】
正题 题目链接:https://vijos.org/p/1197 大意 有5*5个开关,每次选择一个地方时它和它上下左右的开关都会取反,求将所有开关都变成1的最少次数. 解题思路 首先我们知道一个位置 ...
- AcWing 95. 费解的开关(指数型枚举)
95. 费解的开关 题意: 给定一个5x5的方格,共25盏灯 每盏灯有开和关两种状态 每次操作一盏灯时,以该灯为中心的十字形状范围的灯都会改变状态 找到用最少的操作步数使所有的灯都亮着,当步数超过6时 ...
- 使用枚举的位运算实现游戏中Debuff状态的添加和消除
测试使用的是Unity5.6.5版本 对于一些特殊的场合,我们经常需要对一系列的状态设置开关,今天刚好在做游戏中Debuff状态的开发,使用了枚举的位运算实现该功能,这里做一些总结,以便自己查阅复习. ...
- C# 枚举中的位运算
最近用枚举做一个权限控制,在移除某一个权限时一值都得不到解决(离散比较差),网上介绍也少,经过百般搜查,终于找到答案,现多写一份,以后来使用者更易查找. 原文:http://developer.51c ...
- java 枚举 或运算_Objective-C 枚举 中位运算 的使用
前言 Enum,也就是枚举,从C语言开始就有了,C++.Java.Objective-C.Swift这些语言,当然都有对应的枚举类型,功能可能有多有少,但是最核心的还是一个--规范的定义代码中的状态. ...
- C#枚举中的位运算权限分配浅谈
常用的位运算主要有与(&), 或(|)和非(~), 比如: 1 & 0 = 0, 1 | 0 = 1, ~1 = 0 在设计权限时, 我们可以把权限管理操作转换为C#位运算来处理. 第 ...
- 将不确定变为确定~整形变量是否可以进行位运算(像枚举类型一样)
回到目录 如果您看到这个题目,觉得有点怪,那说明你是一个高人,最起码比我高的多,呵呵. 前几天做了一个公用后台管理系统的项目,其中有一个地方涉及到权限管理的,即为每一个按钮赋一个权限,然后它权限汇总到 ...
最新文章
- 从理论支撑到具体应用,万字长文详述 CV 中 Transformer 的广阔天地
- 阿里云数据库POLARDB技术沙龙火热报名中,李飞飞,曹伟 众大神齐到场,200个席位先到先得!...
- 开始使用Bootstrap
- 我的学习之路_第二十三章_HTML
- 【分析】立即购买vs加入购物车,移动电商购买流程差异分析
- kafka mirror_SSL Kafka经纪人从Kafka Mirror Maker迁移到Brooklin的挑战
- linux系统时间代表,Linux上有两种时间,一种是硬件时间,一种是系统时间
- [Java] 蓝桥杯ALGO-143 算法训练 字符串变换
- Atitit 项目管理之道 attilax著
- 服务器搭建centos7系统操作过程(使用系统盘搭建centos7系统)
- 数学建模中的ARMA模型和ARIMA模型的使用实例(含代码)
- 青云服务器上禁用Ubuntu14.04的ipv6
- 戴尔笔记本Windows10安装Ubuntu18.04实现双系统总结
- php博客系统答辩问题,基于PHP个人博客的设计与实现毕业设计答辩 PPT课件
- MFC之RTTI分析(基于侯俊杰的《深入浅出MFC》)
- 一年工作生活总结(转)
- 基于pyecharts的《红楼梦》人物关系可视化
- [摄影基本学习]-02-器材了解(从零开始手把手教你学摄影)
- 小学计算机绘画社团作品展,“小学电脑绘画教学研究”课题
- python如何顺序读取文件夹下的图片及文件