成长轨迹56 【ACM算法之路 百炼poj.grids.cn】【简单枚举】【2811:熄灯问题】
2012-02-25 11:20
239 查看
虽然ac了,但后面对自己的代码有些疑问。。。
题目http://poj.grids.cn/practice/2811
//1、将数组开大一些,使用公式时就可以不用考虑边界
//2、熄灯规则:这一层灯亮,则下一层的对应按键按下
//3、无论开关多少次,将其开次数相加,mod2就可以知道其当前状态
//这样处理,第一行的按键并不会改变
//4、遍历第一层所有按键的情况,因为只有开和关,可以利用二进制+1方式遍历
//模拟二进制,每次加1处理以遍历000000~111111
【wa代码】
【ac标程】
View Code
分析附后
【我的ac代码】
【疑问】
我ac和wa的两个结构到底有什么区别呢?
【wrong】
【right】
仔细看可以知道,
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还不成功是什么情况?!
唔。。。求高人解答了。。。
题目http://poj.grids.cn/practice/2811
//1、将数组开大一些,使用公式时就可以不用考虑边界
//2、熄灯规则:这一层灯亮,则下一层的对应按键按下
//3、无论开关多少次,将其开次数相加,mod2就可以知道其当前状态
//这样处理,第一行的按键并不会改变
//4、遍历第一层所有按键的情况,因为只有开和关,可以利用二进制+1方式遍历
//模拟二进制,每次加1处理以遍历000000~111111
【wa代码】
#include <stdio.h> #include <string.h> int state[6][8],press[6][8];//1、将数组开大一些,使用公式时就可以不用考虑边界 bool deal() { for(int j=1;j<6;j++) for(int k=1;k<7;k++)//2、熄灯规则:这一层灯亮,则下一层的对应按键按下 press[j+1][k]=(state[j][k]+press[j][k]+press[j-1][k]+press[j][k-1]+press[j][k+1])%2; //3、无论开关多少次,将其开次数相加,mod2就可以知道其当前状态 //这样处理,第一行的按键并不会改变 for(int k=1;k<7;k++) if((state[5][k]+press[5][k]+press[4][k]+press[5][k-1]+press[5][k+1])%2) return false; return true; } int main() { int t; scanf("%d",&t); for(int i=0;i<t;i++) { for(int j=0;j<8;j++) state[0][j]=0; for(int j=0;j<6;j++) { state[j][0]=state[j][7]=0; memset(press[j],0,sizeof(press[j])); } for(int j=1;j<6;j++) for(int k=1;k<7;k++) scanf("%d",&state[j][k]); 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;//【这里不跳出还会继续查的。。。】 } } } return 0; }
【ac标程】
View Code
//看下标程。。后面还有我刚刚那个的改正版 #include<stdio.h> int press[6][8]; int puzzle[6][8]; bool guess(){ int i,j; for(i=2;i<=5;i++){ for(j=1;j<=6;j++){ 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; } } for(j=1;j<=6;j++){ if(press[5][j]!=(puzzle[5][j]+press[5][j-1]+press[5][j+1]+press[4][j])%2) return false; } return true; } void process(){ int c; for(c=1;c<=6;c++) press[1][c]=0; while(!guess()){ press[1][1]++; c=1; while(press[1][c]>1){ press[1][c]=0; c++; press[1][c]++; } } } int main(){ int t,i,n,j; for(i=0;i<8;i++) press[0][i]=puzzle[0][i]=0; for(i=1;i<6;i++) press[i][0]=puzzle[i][0]=press[i][7]=puzzle[i][7]=0; scanf("%d",&t); for(n=1;n<=t;n++){ for(i=1;i<=5;i++) for(j=1;j<=6;j++) scanf("%d",&puzzle[i][j]); process(); printf("PUZZLE #%d\n",n); for(i=1;i<=5;i++){ for(j=1;j<=6;j++){ printf("%d ",press[i][j]); } printf("\n"); } } return 0; }
分析附后
【我的ac代码】
//发现press[1][c]<=1这个判断条件可能有错 #include <stdio.h> #include <string.h> int state[6][8],press[6][8];//1、将数组开大一些,使用公式时就可以不用考虑边界 int i; bool deal() { for(int j=1;j<6;j++) for(int k=1;k<7;k++)//2、熄灯规则:这一层灯亮,则下一层的对应按键按下 press[j+1][k]=(state[j][k]+press[j][k]+press[j-1][k]+press[j][k-1]+press[j][k+1])%2; //3、无论开关多少次,将其开次数相加,mod2就可以知道其当前状态 //这样处理,第一行的按键并不会改变 for(int k=1;k<7;k++) if((state[5][k]+press[5][k]+press[4][k]+press[5][k-1]+press[5][k+1])%2) return false; 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; } int main() { int t; scanf("%d",&t); for(i=0;i<t;i++) { for(int j=0;j<8;j++) state[0][j]=0; for(int j=0;j<6;j++) { state[j][0]=state[j][7]=0; memset(press[j],0,sizeof(press[j])); } for(int j=1;j<6;j++) for(int k=1;k<7;k++) scanf("%d",&state[j][k]); int c=1; 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]++; } } } return 0; }
【疑问】
我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还不成功是什么情况?!
唔。。。求高人解答了。。。
相关文章推荐
- 成长轨迹53 【ACM算法之路 百炼poj.grids.cn】【简单枚举】【2747、2810、2692、2977】
- 成长轨迹54 【ACM算法之路 百炼poj.grids.cn】【简单枚举】【2739:计算对数】
- 成长轨迹55 【ACM算法之路 百炼poj.grids.cn】【简单枚举】【2812:恼人的青蛙】
- 成长轨迹58 【ACM算法之路 百炼poj.grids.cn】【递归】【1664:放苹果】
- Openjudge 2811 熄灯问题 枚举 爆搜
- 成长轨迹60 【ACM算法之路 百炼poj.grids.cn】【递归】【2756:二叉树】
- Openjudge 2811 熄灯问题 枚举 爆搜
- 2811 熄灯问题(枚举)
- 成长轨迹61 【ACM算法之路 百炼poj.grids.cn】【动态规划】【2806、1661、2757】
- Openjudge 2811 熄灯问题 枚举 爆搜
- Openjudge 2811 熄灯问题 枚举 爆搜
- 成长轨迹44 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2799、2976、2975、2742】
- 成长轨迹47 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2820:古代密码】
- Openjudge 2811 熄灯问题 枚举 爆搜
- 成长轨迹48 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2818:密码】
- Openjudge 2811 熄灯问题 枚举 爆搜
- 成长轨迹45 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2797:最短前缀】
- 成长轨迹49 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2819:W的密码】
- 成长轨迹50 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2974:487-3279】
- Openjudge 2811 熄灯问题 枚举 爆搜