• 1813(2.1)


    枚举的第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
    ",pres[i][6]);
                    }
                }
                
            }
        return 0;    
    }
    View Code
  • 相关阅读:
    二叉排序树
    #define使用方法
    typedef函数指针使用方法
    ORACLE触发器具体解释
    C++第11周(春)项目2
    建立人际信任的方法
    Error creating bean with name &#39;menuController&#39;: Injection of autowired dependency……
    strtok和strtok_r
    session销毁
    嵌入式相关5
  • 原文地址:https://www.cnblogs.com/ssfzmfy/p/5195510.html
Copyright © 2020-2023  润新知