pku 1222 熄灯

#include <iostream> using namespace std; int map[7][8];//5*6 int result[7][8]; int main() { int N; int cnt = 0; scanf("%d", &N); while(N--) { memset(result, 0, 7*8*sizeof(int)); for(int i = 1; i <= 5; ++i) for(int j = 1; j<= 6; ++j) scanf("%d", &map[i][j]); for(int i = 0; i < 64; ++i) { for(int j = 1; j <= 6; ++j) result[1][j] = (i>>(j-1) & 1); for(int j = 2; j <= 5; ++j) for(int k = 1; k <= 6; ++k) result[j][k] = (map[j-1][k] + result[j-2][k] + result[j-1][k] + result[j-1][k-1] + result[j-1][k+1])%2; bool WAFlag = false; for(int j = 1; j <= 6; ++j) if((result[5][j] + result[4][j] + result[5][j-1] + result[5][j+1])%2 != map[5][j]) { WAFlag = true; break; } if(WAFlag) continue; else { printf("PUZZLE #%d/n", ++cnt); for(int j = 1; j <= 5; ++j) { for(int k = 1; k <= 6; ++k) printf("%d ", result[j][k]); printf("/n"); } break; } } } return 0; } //sums: /* 1. 认识到穷举有时也是需要优化的: 本题从2^32 优化到 2^6; 由穷举第一行,对于每种情况,从第二行起推导出2~5行个位置应该 的取值,再检验第五行是否都可以熄灭,否则继续穷举. 关键是找出优化的条件!! 2. 给map[][]加保护圈有时能简化很多步骤和计算; 3. MOD 的充分运用,也可以简化我们的求解过程; 4. (i>>(j-1) & 1) 的方法产生序列,可以简化穷举, 在计算机中运用位运算,很多时候会简化计算!! */ //大牛如是说: /**************************************************************** 解题方法比较有代表性。 首先题目规定是5*6的矩阵,如果遍历每种情况,即构造一个bool press[5][6]来存储按钮 状态,需要搜索2^30的状态,这显然是不能接受的。 但是可以换个思路想,一个位置press[r][c]为0或者为1由那些因素构成呢?由题意就能知 道有这些因素决定: 1. 这个位置的灯是否为亮的,设为puzzle[r][c] 2. 其上下左右各个按钮是不是按下,即press[r-1][c], press[r][c-1], press[r+1][c], press[r][c+1] 这样就有了一个新的结论,观察上面的条件可知,可以由puzzle[r][c], press[r][c], press[r-1][c], press[r][c-1], press[r][c+1] 这几个条件推出press[r+1][c], 再换句话说,只要第一行有一个确定的结果,就可以推出剩下的各行,而推到最后一行 (第5行)的时候,就可以检测推出的结果是不是能满足要求。 这样只需要枚举第1行的所有情况,即2^6种,就可以完成搜索了。 看了这题自然就联想到校赛那题,也就是3600 Subimage Recognition那题。当时就是想 完全穷举肯定超时。后来发现,只要穷举行或者列的情况就可以,不用全部都穷举。 比如有3*3变成 2*2,只需要穷举从3列中选出2列的所有可能,然后从上往下遍历这个3*2 的矩阵,看是不是能满足2*2的矩阵。 **********************************/  

你可能感兴趣的:(c,优化,存储,360,include,联想)