题意:在一个棋盘上,每个格子摆放有一枚棋子,每一枚棋子的颜色要么是黑色,要么是白色。每次操作可以选择一枚棋子,将它的颜色翻转(黑变白,白变黑),同时将这枚棋子上下左右相邻的四枚棋子的颜色翻转(如果对应位置有棋子的话)。
判断能否通过多次操作将所有棋子都变成黑色或者白色?如果可以,最小操作次数又是多少呢?
思路:二进制枚举第一行的所有情况,不断通过上一行推断当前行的翻转状态。
本蒟蒻的第一篇题解,求大佬拷打" 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; }