fork download
  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5.  
  6. const int N = 22;
  7. const int INF = 1e9;
  8.  
  9. int n;
  10. int a[N][N]; // 初始矩阵
  11. int x[N][N]; // 主动翻转标记
  12.  
  13. int main() {
  14. cin >> n;
  15. for (int i = 1; i <= n; ++i) {
  16. string s;
  17. cin >> s;
  18. for (int j = 1; j <= n; ++j) {
  19. a[i][j] = s[j - 1] - '0';
  20. }
  21. }
  22.  
  23. int ans = INF;
  24. // 枚举第一行的所有状态,共 2^n 种
  25. for (int mask = 0; mask < (1 << n); ++mask) {
  26. memset(x, 0, sizeof x);
  27. // 设置第一行的翻转情况
  28. for (int j = 1; j <= n; ++j) {
  29. x[1][j] = (mask >> (j - 1)) & 1;
  30. }
  31.  
  32. // 递推计算第 2 ~ n 行的翻转情况
  33. for (int i = 1; i < n; ++i) {
  34. for (int j = 1; j <= n; ++j) {
  35. // 根据第 i 行的方程解出 x[i+1][j]
  36. x[i + 1][j] = a[i][j] ^ x[i][j] ^ x[i - 1][j] ^ x[i][j - 1] ^ x[i][j + 1];
  37. }
  38. }
  39.  
  40. // 检查最后一行是否满足全 0
  41. bool ok = true;
  42. for (int j = 1; j <= n; ++j) {
  43. int val = a[n][j] ^ x[n][j] ^ x[n - 1][j] ^ x[n][j - 1] ^ x[n][j + 1];
  44. if (val != 0) {
  45. ok = false;
  46. break;
  47. }
  48. }
  49.  
  50. if (ok) {
  51. int sum = 0;
  52. for (int i = 1; i <= n; ++i)
  53. for (int j = 1; j <= n; ++j)
  54. sum += x[i][j];
  55. ans = min(ans, sum);
  56. }
  57. }
  58.  
  59. if (ans == INF) cout << -1 << endl;
  60. else cout << ans << endl;
  61.  
  62. return 0;
  63. }
Success #stdin #stdout 0s 5320KB
stdin
3
1 1 1
1 1 1
1 1 1
stdout
-1