枚举2--熄灯问题

枚举2--熄灯问题

一、题目:

有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。
每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。
即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。
在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。
给你一个所有灯的初始状态,请你写一个程序,确定需要按下哪些按钮,恰好使得所有的灯都熄灭。

输入:
每个案例由5行组成,每一行包括6个数字。
这些数字以空格隔开,可以是0或1。0表示灯的初始状态是熄灭的,1表示灯的初始状态是点亮的。
样例输入:
0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 0 1 1 0 0
0 1 0 1 0 0

输出
对每个案例,首先输出一行,输出字符串“PUZZLE #m”,其中m是该案例的序号。
接着按照该案例的输入格式输出5行,其中的1表示需要把对应的按钮按下,0则表示不需要按对应的按钮。
每个数字以一个空格隔开。
样例输出:
PUZZLE #1
1 0 0 1 1 1
1 1 0 0 0 0
0 0 0 1 0 0
1 1 0 1 0 1
1 0 1 1 0 1

二、代码及分析

灯泡阵

这里用6行8列是保证按规定按钮影响的都是周围5盏灯的情况,注意,不是7行8列,因为最后一行不会被下一行影响

  1 /*
  2 分析:
  3     方法一:枚举所有可能
  4         总共5*6=30展灯,所有可能情况为2^30,所以肯定不行
  5     方法二:如果局部状态确定,那么其余状态也被确定,那么我们只用例举局部状态即可
  6         当第一行的灯光操作之后,我们可以操作第二行的灯光将第一行的灯光全部熄灭,而此时第二行的灯光也是唯一确定的。
  7         而第三,第四等行影响不到第一行。同理第二行的灯光确定后,第三行把第二行全部调熄,那么第三行也是唯一确定的。
  8         同理第四行,第五行也是唯一确定的。
  9         所以当确定第一行之后,所有的行都是唯一确定的,我们看这个所有灯的唯一确定的情况是否使所有的灯熄灭从而判断解是否为可行解。
 10         其实我们只要判断第五行即可,因为照之前的规则,前四行肯定是熄灯的。
 11         所以我们只用枚举第一行就可以枚举所有的情况。
 12         情况总数为:2^6,每种情况都要调所有的30盏灯,执行次数为2^6*5*6(下面的代码编程我们选这种)
 13
 14         优化:
 15             若是把列看成行,情况总数为2^5,执行次数为2^5*6*5
 16
 17
 18         执行2^6的时候,我们可以用6层循环,我们也可以用数字的二进制来表示。我们选择用数字的二进制来表示。
 19
 20
 21
 22 */
 23
 24
 25 #include <iostream>
 26 using namespace std;
 27 int puzzle[6][8],press[6][8];//这里用6行8列是保证按规定按钮影响的都是周围5盏灯的情况,注意,不是7行8列,因为最后一行不会被下一行影响
 28
 29 bool guess(){//这个函数时对第一行每一个的选择情况进行判断
 30     int c,r;//r表示行,c表示列
 31     for(r=1;r<5;r++){
 32         for(c=1;c<7;c++){
 33             //下一行的按键是为了把上一行的按键整熄,作用每一个灯的有上下左右自己和自己的初始情况
 34             //下按=(自己初始状态+自己按+左按+右按+上按)
 35             press[r+1][c]=(puzzle[r][c]+press[r][c]+press[r][c-1]+press[r][c+1]+press[r-1][c])%2;
 36         }
 37     }
 38     for(c=1;c<7;c++){//判断最后一行是否全部熄灯
 39         //如果最后一行各个按钮对灯的作用与初始状态保存一致,则说明是熄灯的。
 40         //例如如果总的作用为1,表示按一下,如果之前初始状态也是1,那么原来亮着的灯就熄了
 41         //对一个灯按奇数次的效果和按一次的效果一样
 42         if((press[5][c-1]+press[5][c]+press[5][c+1]+press[4][c])%2!=puzzle[5][c])
 43             return (false);
 44     }
 45     return (true);
 46 }
 47
 48 void enumerate(){//这个函数枚举第一行所有的情况
 49     int c;
 50     bool success;
 51     for(c=1;c<7;c++){
 52         press[1][c]=0;//对按钮方阵初始化
 53     }
 54     /*
 55         press[1][1]:1   c:1   press[1][c]=press[1][1]>1不成立  1 0 0 0 0 0 表示的是第一盏灯开,其余5盏灯熄
 56         press[1][1]:2   c:1   press[1][c]=press[1][1]>1成立    press[1][c]=press[1][1]:0  c++:2  press[1][c]=press[1][2]:1
 57             press[1][c]=press[1][2]>1不成立  0 1 0 0 0 0 表示的是第二盏灯开,其余5盏灯熄
 58         press[1][1]:3   c:1   press[1][c]=press[1][1]>1成立    press[1][c]=press[1][1]:0  c++:2  press[1][c]=press[1][2]:2
 59             press[1][c]=press[1][2]>1成立    press[1][c]=press[1][2]:0  c++:3  press[1][c]=press[1][3]:1
 60             0 0 1 0 0 0 表示的是第三盏灯开,其余5盏灯熄
 61         以此类推
 62
 63     */
 64     while(guess()==false){
 65         press[1][1]++;
 66         c=1;
 67         while(press[1][c]>1){
 68             press[1][c]=0;
 69             c++;
 70             press[1][c]++;
 71         }
 72     }
 73     return;
 74 }
 75
 76 int main(){
 77     freopen("2in.txt","r",stdin);
 78     int cases,i,r,c;
 79
 80     //对周围按钮进行初始化
 81     for(r=0;r<6;r++)
 82         press[r][0]=press[r][7]=0;
 83     for(c=1;c<7;c++){
 84         press[0][c]=0;
 85     }
 86     //录入数据,灯泡的初始状态
 87     for(r=1;r<6;r++){
 88         for(c=1;c<7;c++){
 89             scanf("%d",&puzzle[r][c]);
 90         }
 91     }
 92
 93     enumerate();//进行枚举判定
 94     printf("PUZZLE #1\n");
 95     //输出结果
 96     for(r=1;r<6;r++){
 97         for(c=1;c<7;c++){
 98             printf("%d ",press[r][c]);
 99         }
100         printf("\n");
101     }
102     return 0;
103 }
时间: 2024-10-09 09:28:05

枚举2--熄灯问题的相关文章

枚举算法——熄灯问题

枚举法练习: 题目: 有 一个由按钮组成的矩阵,其中每行有6个按钮,共5行.每个按钮的位置上有一盏灯.当按下一个按钮后,该按钮以及周围位置(上边.下边.左边.右边)的灯都 会改变一次.即,如果灯原来是点亮的,就会被熄灭:如果灯原来是熄灭的,则会被点亮.在矩阵角上的按钮改变3盏灯的状态:在矩阵边上的按钮改变4盏灯的状 态:其他的按钮改变5盏灯的状态. 在 上图中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状态的改变.对矩阵中的每盏灯设置一个初始状态.请你按按钮,直至每一盏等都熄灭.与一盏

程序设计与算法(二)算法基础》《第一周 枚举》熄灯问题 POJ-1222

https://www.cnblogs.com/huashanqingzhu/p/7278930.html http://bailian.openjudge.cn/practice/12221222:EXTENDED LIGHTS OUT 这道题我花了比较多的时间才想清楚,比较难想的地方在第一行的枚举,假设第一行6个元素是 0 1 0 1 0 1, 一盏灯只有亮和灭两个状态,每盏灯只有两个操作,按下开关与不按开关,我之前以为枚举的是0~63,即0000 0000 ~1111 1111, 这种想法

POJ1222熄灯问题【位运算+枚举】

EXTENDED LIGHTS OUT Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14231   Accepted: 8817 Description In an extended version of the game Lights Out, is a puzzle with 5 rows of 6 buttons each (the actual puzzle has 5 rows of 5 buttons ea

算法设计 熄灯问题(枚举法)

题目描述: 有一个由按钮组成的矩阵,其中每行有6个按钮,共5行.每个按钮的位置上有一盏灯.当按下一个按钮后,该按钮以及周围位置(上边.下边.左边.右边)的灯都会改变一次.即,如果灯原来是点亮的,就会被熄灭:如果灯原来是熄灭的,则会被点亮.在矩阵角上的按钮改变3盏灯的状态:在矩阵边上的按钮改变4盏灯的状态:其他的按钮改变5盏灯的状态. 所以在5x6的矩阵中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状态的改变.对矩阵中的每盏灯设置一个初始状态.请你按按钮,直至每一盏等都熄灭.与一盏灯毗邻

算法学习 -- 枚举

在学习枚举算法之前,首先问有关枚举的几个问题 1. 为什么要进行枚举? 2. 需要对哪些对象进行枚举? 3. 如何进行枚举? 4. 枚举的结束条件是什么? 现在针对两个使用枚举算法的实例对以上问题进行分析. 实例一:熄灯问题 给定一个5×6的棋盘,上面有灯,每个灯都有各自的按钮,每个按钮按下去都会使其自己和周围的上下左右四盏灯改变(原来熄灭的变亮,原来亮的变灭),如何操作按钮使这个棋盘上所有灯都熄灭. 实例二:青蛙问题 一个5000×5000的稻田,有很多青蛙从这个稻田上跳过,每只青蛙跳过的步长

ACM/ICPC 之 枚举(POJ1681-画家问题+POJ1166-拨钟问题)

POJ1681-画家问题 枚举的经典例题,枚举第一行即可,其余行唯一. 1 //画家问题,y表示黄色,w表示白色,怎样让墙上所有方格为y,操作类似熄灯问题poj1222 2 //memory 136K Time: 297 Ms 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 9 #define INF

C# 枚举

一.在学习枚举之前,首先来听听枚举的优点. 1.枚举能够使代码更加清晰,它允许使用描述性的名称表示整数值. 2.枚举使代码更易于维护,有助于确保给变量指定合法的.期望的值. 3.枚举使代码更易输入. 二.枚举说明 1.简单枚举 枚举使用enum关键字来声明,与类同级.枚举本身可以有修饰符,但枚举的成员始终是公共的,不能有访问修饰符.枚举本身的修饰符仅能使用public和internal. 枚举是值类型,隐式继承自System.Enum,不能手动修改.System.Enum本身是引用类型,继承自S

C++ 枚举定义

我们在平常的编程中,时常需要为一些属性定义一组可以选择的值,比如文件打开的状态可能会有三种:输入 输出和追加 我们一般情况下记录这些状态是让每一个状态和一个常数相对应   比如 1 const int input=0; 2 const int output=1; 3 const int append=2; 这个方法虽然也是可以得,不过它有一个明显的缺点就是    没有指出这些值是相关联的 而C++中的  枚举  提供了一种替代的方法   不但可以定义常数集   还可以将其聚集成组    如下:

java 枚举常用操作

在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. Java代码 public enum Color { } JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强. Java代码 enum Signal { } public class TrafficLight { public void change() {