题意
传送门 POJ 1222
题解
枚举第一行的开关是否翻转的状态,此时决定 L 0 j L_{0j} L0j 的状态的只有 L 1 j L_{1j} L1j 一个开关,依次类推可以求出所有的开关翻转状态。对于枚举的每一个状态,判断最后一行是否全零即可判断该方案是否可行。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define abs(x) ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-5
#define PI 3.14159265358979323846
#define MAX_N 20
using namespace std;
const int dx[5] = {0, 1, -1, 0, 0};
const int dy[5] = {0, 0, 0, 1, -1};
const int R = 5, C = 6;
int L[R][C];
int flip[R][C];
// 求 (x, y) 位置开关状态
int get(int x, int y){
int s = L[x][y];
for(int i = 0; i < 5; i++){
int nx = x + dx[i], ny = y + dy[i];
if(nx >= 0 && nx < R && ny >= 0 && ny < C){
s ^= flip[nx][ny];
}
}
return s;
}
int main(){
int n;
scanf("%d", &n);
for(int t = 1; t <= n; t++){
for(int x = 0; x < R; x++){
for(int y = 0; y < C; y++){
scanf("%d", &L[x][y]);
}
}
// 枚举第一行所有状态
for(int i = 0; i < 1 << C; i++){
memset(flip, 0, sizeof(flip));
for(int j = 0; j < C; j++) flip[0][j] = 1 & (i >> j);
for(int x = 1; x < R; x++){
for(int y = 0; y < C; y++){
if(get(x - 1, y) == 1) flip[x][y] = 1;
}
}
int s = 0;
for(int y = 0; y < C; y++) s |= get(R - 1, y);
if(s == 0){
printf("PUZZLE #%d\n", t);
for(int x = 0; x < R; x++){
for(int y = 0; y < C; y++){
printf("%d%c", flip[x][y], y == C - 1 ? '\n' : ' ');
}
}
break;
}
}
}
return 0;
}