• 算法设计 熄灯问题


    题目描述:

      有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。

      所以在5x6的矩阵中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状态的改变。对矩阵中的每盏灯设置一个初始状态。请你按按钮,直至每一盏等都熄灭。与一盏灯毗邻的多个按钮被按下时,一个操作会抵消另一次操作的结果。在下图中,第2行第3、5列的按钮都被按下,因此第2行、第4列的灯的状态就不改变。

      请你写一个程序,确定需要按下哪些按钮,恰好使得所有的灯都熄灭。根据上面的规则,我们知道

      1)第2次按下同一个按钮时,将抵消第1次按下时所产生的结果。因此,每个按钮最多只需要按下一次;

      2)各个按钮被按下的顺序对最终的结果没有影响;

      3)对第1行中每盏点亮的灯,按下第2行对应的按钮,就可以熄灭第1行的全部灯。如此重复下去,可以熄灭第1、2、3、4行的全部灯。同样,按下第1、2、3、4、5列的按钮,可以熄灭前5列的灯。

    要求样例出入,输出所需的操作。

    解题思路:

      为了方便,给每个灯的位置定一个坐标,得到一个5x6的数组,但是为了避免第一行,第一列最后一列需要额外的操作,我们讲数组设定为6x8的二维数组。

      puzzle[i][j]表示第i行第j列上灯的初试状态,1为亮,0为灭;

      press[i][j]表示要不要按下ij位置的灯,1为按下;

      如果这样的话有2的30次方种情况,太复杂,对算法进行优化,我们发现了规律

    如果位置(1,j)的灯亮,则press[2][j]的值必为1;反之亦然,所有通过操作,将第一行的灯全部熄灭,而3,4,5行不受影响,继续后面的操作。

    代码如下:

     1 #include "stdio.h"
     2 
     3 int puzzle[6][8];
     4 int press[6][8]; 
     5 
     6 bool guess(){
     7     int i,j;
     8          for(i=2;i<6;i++){
     9               for(j=1;j<7;j++){
    10                    press[i][j]=(press[i-1][j]+puzzle[i-1][j]+press[i-1][j-1]+press[i-2][j]+press[i-1][j+1])%2;
    11                   }
    12              }
    13          for(j=1;j<=6;j++){
    14             if(press[5][j]!=(puzzle[5][j]+press[5][j-1]+press[5][j+1]+press[4][j])%2)
    15                return false;
    16              }
    17          return true;
    18     }
    19 void process(){
    20     int c;
    21     for(c=1;c<7;c++)
    22         press[1][c]=0;
    23     while(!guess()){
    24         press[1][1]++;
    25         c=1;
    26         while(press[1][c]>1){
    27             press[1][c]=0;
    28             c++;
    29             press[1][c]++; 
    30           }
    31      }
    32 }
    33 
    34 int main(){
    35     int i=0,j=0;
    36     for(i=0;i<6;i++)
    37         puzzle[i][0]=puzzle[i][7]=press[i][0]=press[i][7]=0;
    38     for(j=0;j<8;j++)
    39         puzzle[0][j]=puzzle[5][j]=press[0][j]=press[5][j]=0;
    40         
    41     for(i=1;i<6;i++)
    42         for(j=1;j<7;j++)
    43         scanf("%d",&puzzle[i][j]); 
    44     
    45     process();    
    46     printf("press is:
    ");
    47         
    48     for(i=1;i<6;i++){ 
    49         for(j=1;j<7;j++){ 
    50         printf("%d ",press[i][j]); 
    51         } 
    52         printf("
    ");
    53     } 
    54 }

    源码下载(百度云):链接: http://pan.baidu.com/s/1ntOqG7R 密码: ewij

  • 相关阅读:
    html5本地存储之localstorage 、本地数据库、sessionStorage简单使用示例
    HTMl5的存储方式sessionStorage和localStorage详解
    浏览器文档模式设置
    页面缓存
    SQL Server死锁总结
    读写分离,读写分离死锁解决方案,事务发布死锁解决方案,发布订阅死锁解决方案
    页面缓存
    HTML5 history API,创造更好的浏览体验
    【转】编写高质量代码改善C#程序的157个建议——建议96:成员应优先考虑公开基类型或接口
    【转】编写高质量代码改善C#程序的157个建议——建议95:避免在构造方法中调用虚成员
  • 原文地址:https://www.cnblogs.com/SeekHit/p/4897669.html
Copyright © 2020-2023  润新知