• 成长轨迹56 【ACM算法之路 百炼poj.grids.cn】【枚举】【2811:熄灯问题】


    虽然ac了,但后面对自己的代码有些疑问。。。

    题目http://poj.grids.cn/practice/2811

    //1、将数组开大一些,使用公式时就可以不用考虑边界
    //2、熄灯规则:这一层灯亮,则下一层的对应按键按下
    //3、无论开关多少次,将其开次数相加,mod2就可以知道其当前状态
    //这样处理,第一行的按键并不会改变
    //4、遍历第一层所有按键的情况,因为只有开和关,可以利用二进制+1方式遍历
    //模拟二进制,每次加1处理以遍历000000~111111

    【wa代码】

     1 #include <stdio.h>
    2 #include <string.h>
    3 int state[6][8],press[6][8];//1、将数组开大一些,使用公式时就可以不用考虑边界
    4
    5 bool deal()
    6 {
    7 for(int j=1;j<6;j++)
    8 for(int k=1;k<7;k++)//2、熄灯规则:这一层灯亮,则下一层的对应按键按下
    9 press[j+1][k]=(state[j][k]+press[j][k]+press[j-1][k]+press[j][k-1]+press[j][k+1])%2;
    10 //3、无论开关多少次,将其开次数相加,mod2就可以知道其当前状态
    11 //这样处理,第一行的按键并不会改变
    12
    13 for(int k=1;k<7;k++)
    14 if((state[5][k]+press[5][k]+press[4][k]+press[5][k-1]+press[5][k+1])%2)
    15 return false;
    16
    17 return true;
    18 }
    19
    20 int main()
    21 {
    22 int t;
    23 scanf("%d",&t);
    24 for(int i=0;i<t;i++)
    25 {
    26 for(int j=0;j<8;j++)
    27 state[0][j]=0;
    28 for(int j=0;j<6;j++)
    29 {
    30 state[j][0]=state[j][7]=0;
    31 memset(press[j],0,sizeof(press[j]));
    32 }
    33
    34 for(int j=1;j<6;j++)
    35 for(int k=1;k<7;k++)
    36 scanf("%d",&state[j][k]);
    37
    38
    39 int c=1;
    40 while(press[1][c]<=1)//这里c是这次处理中被修改的最后一位
    41 //4、遍历第一层所有按键的情况,因为只有开和关,可以利用二进制+1方式遍历
    42 //模拟二进制,每次加1处理以遍历000000~111111
    43 {
    44 c=1;
    45 press[1][c]++;
    46 while(press[1][c]>1)
    47 {
    48 if(c==6)
    49 break;
    50 press[1][c]=0;
    51 c++;
    52 press[1][c]++;
    53 }
    54
    55 if(deal())
    56 {
    57 printf("PUZZLE #%d\n",i+1);
    58 for(int j=1;j<6;j++)
    59 {
    60 printf("%d",press[j][1]);
    61 for(int k=2;k<7;k++)
    62 printf(" %d",press[j][k]);
    63 printf("\n");
    64
    65 }
    66 break;//【这里不跳出还会继续查的。。。】
    67 }
    68 }
    69 }
    70 return 0;
    71 }



    【ac标程】

    View Code
     1 //看下标程。。后面还有我刚刚那个的改正版
    2 #include<stdio.h>
    3 int press[6][8];
    4 int puzzle[6][8];
    5 bool guess(){
    6 int i,j;
    7 for(i=2;i<=5;i++){
    8 for(j=1;j<=6;j++){
    9 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;
    10 }
    11 }
    12 for(j=1;j<=6;j++){
    13 if(press[5][j]!=(puzzle[5][j]+press[5][j-1]+press[5][j+1]+press[4][j])%2)
    14 return false;
    15 }
    16 return true;
    17 }
    18 void process(){
    19 int c;
    20 for(c=1;c<=6;c++)
    21 press[1][c]=0;
    22 while(!guess()){
    23 press[1][1]++;
    24 c=1;
    25 while(press[1][c]>1){
    26 press[1][c]=0;
    27 c++;
    28 press[1][c]++;
    29 }
    30 }
    31 }
    32 int main(){
    33 int t,i,n,j;
    34 for(i=0;i<8;i++)
    35 press[0][i]=puzzle[0][i]=0;
    36 for(i=1;i<6;i++)
    37 press[i][0]=puzzle[i][0]=press[i][7]=puzzle[i][7]=0;
    38 scanf("%d",&t);
    39 for(n=1;n<=t;n++){
    40 for(i=1;i<=5;i++)
    41 for(j=1;j<=6;j++)
    42 scanf("%d",&puzzle[i][j]);
    43 process();
    44 printf("PUZZLE #%d\n",n);
    45 for(i=1;i<=5;i++){
    46 for(j=1;j<=6;j++){
    47 printf("%d ",press[i][j]);
    48 }
    49 printf("\n");
    50 }
    51 }
    52 return 0;
    53 }


    分析附后
    【我的ac代码】

     1 //发现press[1][c]<=1这个判断条件可能有错
    2 #include <stdio.h>
    3 #include <string.h>
    4 int state[6][8],press[6][8];//1、将数组开大一些,使用公式时就可以不用考虑边界
    5 int i;
    6 bool deal()
    7 {
    8 for(int j=1;j<6;j++)
    9 for(int k=1;k<7;k++)//2、熄灯规则:这一层灯亮,则下一层的对应按键按下
    10 press[j+1][k]=(state[j][k]+press[j][k]+press[j-1][k]+press[j][k-1]+press[j][k+1])%2;
    11 //3、无论开关多少次,将其开次数相加,mod2就可以知道其当前状态
    12 //这样处理,第一行的按键并不会改变
    13
    14 for(int k=1;k<7;k++)
    15 if((state[5][k]+press[5][k]+press[4][k]+press[5][k-1]+press[5][k+1])%2)
    16 return false;
    17
    18 printf("PUZZLE #%d\n",i+1);
    19 for(int j=1;j<6;j++)
    20 {
    21 printf("%d",press[j][1]);
    22 for(int k=2;k<7;k++)
    23 printf(" %d",press[j][k]);
    24 printf("\n");
    25 }
    26 return true;
    27 }
    28
    29 int main()
    30 {
    31 int t;
    32 scanf("%d",&t);
    33 for(i=0;i<t;i++)
    34 {
    35 for(int j=0;j<8;j++)
    36 state[0][j]=0;
    37 for(int j=0;j<6;j++)
    38 {
    39 state[j][0]=state[j][7]=0;
    40 memset(press[j],0,sizeof(press[j]));
    41 }
    42
    43 for(int j=1;j<6;j++)
    44 for(int k=1;k<7;k++)
    45 scanf("%d",&state[j][k]);
    46
    47 int c=1;
    48 while(!deal())
    49 //4、遍历第一层所有按键的情况,因为只有开和关,可以利用二进制+1方式遍历
    50 //模拟二进制,每次加1处理以遍历000000~111111
    51 {
    52 c=1;
    53 press[1][c]++;
    54 while(press[1][c]>1)
    55 {
    56 if(c==6)
    57 break;
    58 press[1][c]=0;
    59 c++;
    60 press[1][c]++;
    61 }
    62
    63 }
    64 }
    65 return 0;
    66 }



      

    【疑问】
    我ac和wa的两个结构到底有什么区别呢?
    【wrong】

            int c=1;
    while(press[1][c]<=1)//这里c是这次处理中被修改的最后一位
    //4、遍历第一层所有按键的情况,因为只有开和关,可以利用二进制+1方式遍历
    //模拟二进制,每次加1处理以遍历000000~111111
    {
    c=1;
    press[1][c]++;
    while(press[1][c]>1)
    {
    if(c==6)
    break;
    press[1][c]=0;
    c++;
    press[1][c]++;
    }

    if(deal())
    {
    printf("PUZZLE #%d\n",i+1);
    for(int j=1;j<6;j++)
    {
    printf("%d",press[j][1]);
    for(int k=2;k<7;k++)
    printf(" %d",press[j][k]);
    printf("\n");

    }
    break;//【这里不跳出还会继续查的。。。】
    }
    }



     【right】

            bool deal()
    {
    ……
    printf("PUZZLE #%d\n",i+1);
    for(int j=1;j<6;j++)
    {
    printf("%d",press[j][1]);
    for(int k=2;k<7;k++)
    printf(" %d",press[j][k]);
    printf("\n");

    }
    return true
    }
    while(!deal())
    //4、遍历第一层所有按键的情况,因为只有开和关,可以利用二进制+1方式遍历
    //模拟二进制,每次加1处理以遍历000000~111111
    {
    c=1;
    press[1][c]++;
    while(press[1][c]>1)
    {
    if(c==6)
    break;
    press[1][c]=0;
    c++;
    press[1][c]++;
    }

    }


      仔细看可以知道,
    1、第一个的if(deal())里边的东西被放进了第二个的deal()的return true之前,这两个写法是等价的
    2、第二个的while条件做出了修改,但是第一个的if(deal())里边也有break,所以这两个也等价

      两个的区别就是第一个有条件press[1][c]<=1,第二个没有。同时两个都有deal()如果成功就跳出的条件

     但是这个c是修改的最后一位啊,它跳出的条件只能是最后一位是2.。。既然这样错了,意思是第一个(带有条件press[1][c]<=1)可能在deal()成功之前跳出(因为成功之后就跳出了,就算那个条件在成功之后不满足那也无所谓。所以,只能是在成功之前跳出导致出错),那么就是说。。press[1][c]在>1时还不应跳出,因为deal()还没有成功,再等一下就成功了。。。但是从000000遍历到111111还不成功是什么情况?!

      唔。。。求高人解答了。。。

  • 相关阅读:
    html实现时间输入框
    使用textarea标签代替input标签可以实现输入框的大小调节,自动换行,滚动条显示
    requests模块的使用
    抓包工具Fiddler使用教程
    git 使用merge 对本地分支进行合并 并进行代码提交的流程
    js常用方法汇总
    js对象排序
    原生javasxript获取浏览器的滚动距离和可视窗口的高度
    深度对象拷贝
    curl扩展代码
  • 原文地址:https://www.cnblogs.com/zeedmood/p/2367575.html
Copyright © 2020-2023  润新知