简要概括一下题目:有一个5乘5的01矩阵,通过变换让其中元素全变成1,求最小变换的次数。
这里的变换是指一个元素本身和他的上下左右共五个元素异或1。
思路:首先对第一排确定一种变换方案,将第一排固定,如果为该位置是0,通过变换第二排的该位置元素使他变成1即可,依次向下求得最优方案。
枚举第一排的变换方案,每一个位置可选择变或不变,则考虑用状态压缩,枚举0到31这32个数(2的5次方),二进制下1表示变,0不变。
#include <bits/stdc++.h>
using namespace std;
int dx[5] = {-1, 0, 1, 0, 0};
int dy[5] = {0, 1, 0, -1, 0};
int a[6][6], b[6][6], ans, ans1;
void cal(int x, int y) {//变换操作
for (int i = 0; i < 5; i ++) {
int x1 = x + dx[i], y1 = y + dy[i];
if (x1 >= 1 && x1 <= 5 && y1 >= 1 && y1 <= 5)
b[x1][y1] ^= 1;
}
}
void dfs(int x) {//搜索
if (x > 5) return ;
for (int i = 1; i <= 5; i ++) {
if (b[x - 1][i] == 0) cal(x, i), ans ++;
else continue;
}
dfs(x + 1);
}
int main() {
int n; cin >> n;
while (n --) {
ans1 = 0x3f3f3f3f;
for (int i = 1; i <= 5; i ++) {
for (int j = 1; j <= 5; j ++) {
char str; cin >> str;
if (str == '0') a[i][j] = 0;
else a[i][j] = 1;
}
}
for (int bit = 0; bit <= 31; bit ++) {//状态压缩枚举第一排
ans = 0;
int res = 0, f = 0;
memcpy(b, a, sizeof(b));
int cnt = bit;
for (; cnt; cnt >>= 1) {//位运算,取出每一位
res ++;
if (cnt & 1) cal(1, res), ans ++;//处理第一排
}
dfs(2);//从第二排依次向下处理
for (int m = 1; m <= 5; m ++)
if (b[5][m] == 0) {//无解
f = 1;
break;
}
if (f == 1) continue ;
ans1 = min(ans1, ans);
}
if (ans1 > 6) cout << -1 << endl;
else cout << ans1 << endl;
}
}
399

被折叠的 条评论
为什么被折叠?



