题意:在一个棋盘上,每个格子摆放有一枚棋子,每一枚棋子的颜色要么是黑色,要么是白色。每次操作可以选择一枚棋子,将它的颜色翻转(黑变白,白变黑),同时将这枚棋子上下左右相邻的四枚棋子的颜色翻转(如果对应位置有棋子的话)。
判断能否通过多次操作将所有棋子都变成黑色或者白色?如果可以,最小操作次数又是多少呢?
思路:二进制枚举第一行的所有情况,不断通过上一行推断当前行的翻转状态。
本蒟蒻的第一篇题解,求大佬拷打
" src="https://uploadfiles.nowcoder.com/images/20220815/318889480_1660553763930/8B36D115CE5468E380708713273FEF43" />
" src="https://uploadfiles.nowcoder.com/images/20220815/318889480_1660553763930/8B36D115CE5468E380708713273FEF43" />
" src="https://uploadfiles.nowcoder.com/images/20220815/318889480_1660553763930/8B36D115CE5468E380708713273FEF43" />
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
int a[105][15], tt[105][15];
int f(int key) {
int ans = INT_MAX;
for (int i = 0; i < 1 << m; i++) {
for (int j = 0; j < n; j++)
for (int k = 0; k < m; k++)
tt[j][k] = a[j][k];
int res = 0;
for (int j = 0; j < m; j++) {
if ((i >> j) & 1) {
tt[0][j] ^= 1;
if (j != 0)
tt[0][j - 1] ^= 1;
if (j != m - 1)
tt[0][j + 1] ^= 1;
if (n != 1)
tt[1][j] ^= 1;
res++;
}
}
for (int j = 1; j < n; j++) {
for (int k = 0; k < m; k++) {
if (tt[j - 1][k] != key) {
res++;
tt[j - 1][k] ^= 1;
tt[j][k] ^= 1;
if (j != n - 1)
tt[j + 1][k] ^= 1;
if (k != 0)
tt[j][k - 1] ^= 1;
if (k != m - 1)
tt[j][k + 1] ^= 1;
}
}
}
bool flag = 1;
for (int j = 0; j < m; j++) {
if (tt[n - 1][j] != key) {
flag = 0;
break;
}
}
if (flag)
ans = min(res, ans);
}
return ans;
}
void solve() {
cin >> n >> m;
char ch;
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
//注意题目中的输入格式是一连串数字,不能直接cin>>a[i][j]
cin>>ch;
a[i][j]=ch-'0';
}
}
int ans = min(f(1), f(0));
if (ans == INT_MAX)
cout << "Impossible" << endl;
else
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
// cin>>t;
while (t--)
solve();
return 0;
}



京公网安备 11010502036488号