题目 传送门
简要思路: 枚举第一行所有的操作可能性(2^5=32),之后对于每一种情况下的第一行,用第一行下方的第二行的灯来把第一行里面是0的全部变成1,一直到最后一行。由于没有下一行来改变最后一行的0,1情况,所以若此时最后一行不全为1的话,就不满足题意
Code:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int inf = 0x3f3f3f3f;
const int maxn = 10;
char mp[maxn][maxn];
char tmp[maxn][maxn];
int dx[]={0,-1,0,1,0}, dy[]={1,0,-1,0,0};//改变上下左右和自己的灯的状态
int n = 5;
void turn (int x, int y) {
for (int i=0;i<5;i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx>=0&&nx<n&&ny>=0&&ny<n) {
tmp[nx][ny] = '0' + !(tmp[nx][ny] - '0');
}
}
}
int get_step() {
int step, ans = inf;
for (int i=0;i<(1 << n);i++) {//枚举每个第一行的操作情况
memcpy(tmp, mp, sizeof(mp));//变回原来mp[][]
step = 0;
for (int j=0;j<n;j++) {
if ((i >> j) & 1) {
turn(0, j);
step++;
}
}
for (int i=0;i<n-1;i++) {
for (int j=0;j<n;j++) {
if (tmp[i][j] == '0') {
turn(i+1, j);//按它下面的灯的开关
step++;
}
}
}
bool is_ok = true;
for (int i=0;i<n;i++) {
if (tmp[n-1][i] != '1') {
is_ok = false;
break;
}
}
if (!is_ok) continue;
ans = min(ans, step);
}
return ans<=6?ans:-1;
}
int main()
{
int T;
scanf("%d", &T);
while (T--) {
for (int i=0;i<n;i++) {
scanf("%s", mp[i]);
}
printf("%d\n", get_step());
}
return 0;
}