枚举的第5题,咋一看没有思路。仔细研究样列,又找到了该游戏 ,实践了一下,才稍微有些思路。

 

实际上答案基本在题干中:根据上面的规则,我们知道1)第2次按下同一个按钮时,将抵消第1次按下时所产生的结果。因此,每个按钮最多只需要按下一次;2)各个按钮被按下的顺序对最终的结果没有影响;3)对第1行中每盏点亮的灯,按下第2行对应的按钮,就可以熄灭第1行的全部灯。如此重复下去,可以熄灭第1、2、3、4行的全部灯。

可是第5行的灯如何熄灭呢?

这是本题的关键,谁会影响到最后一行的结果呢?2灭1,3灭2...,只有第一行的操作会影响到最后一行。所以可以枚举第一行的所有情况2^6.

第一行的0~63共64种情况,可以和二进制一一对应,比较朴素的方法是:

for (int k=0;k<=63;k++){//枚举第一行的灯被按下的所有情况(2^6=64)
....
  for (int j=1;j<=6;j++){//判断第一行的j灯是否被按下,按下则press[1][j]=1;
    int n=pow(2,6-j);//取二进制的第6-j位
    pres[1][j]=1&&(k&n);//如果第6-j位 存在,则按下,即值变为1;
    if (pres[1][j]==1){
      a[1][j]=!a[1][j];a[2][j]=!a[2][j];a[1][j-1]=!a[1][j-1];a[1][j+1]=!a[1][j+1];
    }//按下[1][j]后的变化
    }

 

......

而:int n=pow(2,6-j);//取二进制的第6-j位 
    pres[1][j]=1&&(k&n);//如果第6-j位 存在,则按下,即值变为1; 

可以简写为:
pres[1][j]=1&(k>>6-j);//如果第6-j位 存在,则按下,即值变为1;
   即k左移6-j位(即k/2^(6-j))后的值与1相与,这样正好取出来第一位二进制数

#include<cstdio>
#include<cmath>
#include<cstring>
int a[200][200],b[200][200];
int pres[200][200]={0};
int main(){
    //freopen("1813.in","r",stdin);
    //freopen("1813.out","w",stdout);
    for (int i=1;i<=5;i++)
        for(int j=1;j<=6;j++)
            scanf("%d",&a[i][j]);
    memcpy(&b,&a,sizeof(a));
    for (int k=0;k<=63;k++){//枚举第一行的灯被按下的所有情况(2^6=64) 
        memcpy(&a,&b,sizeof(b));//赋初值 
        memset(pres,0,sizeof(pres));//初始化 
        for (int j=1;j<=6;j++){//判断第一行的j灯是否被按下,按下则press[1][j]=1; 
        //    int n=pow(2,6-j);//取二进制的第6-j位 
            pres[1][j]=1&(k>>6-j);//如果第6-j位 存在,则按下,即值变为1; 
            if (pres[1][j]==1){ 
                a[1][j]=!a[1][j];a[2][j]=!a[2][j];a[1][j-1]=!a[1][j-1];a[1][j+1]=!a[1][j+1];
            }//按下[1][j]后的变化
           }     
        for(int i=1;i<=4;i++)
            for(int j=1;j<=6;j++)
                if (a[i][j]==1){
                    a[i+1][j]=!a[i+1][j];a[i][j]=!a[i][j];a[i+1][j-1]=!a[i+1][j-1];a[i+1][j+1]=!a[i+1][j+1];a[i+2][j]=!a[i+2][j];
                    pres[i+1][j]=1;
                }
        int i,j,sum=0;
        for (int j=1;j<=6;j++)             sum=sum+a[5][j];
        if (sum==0) {
            for ( i=1;i<=5;i++){
                for ( j=1;j<=5;j++)
                    printf("%d ",pres[i][j]);
                printf("%d\n",pres[i][6]);
                }
            }
            
        }
    return 0;    
}
View Code