fork download
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. int main() {
  5. int n;
  6. cin >> n;
  7. vector<int> row(n, 0); // 存储每一行初始矩阵的二进制表示
  8. for (int i = 0; i < n; ++i) {
  9. string s;
  10. cin >> s;
  11. int num = 0;
  12. for (int j = 0; j < n; ++j) {
  13. if (s[j] == '1') num |= (1 << j); // 第 j 位对应列 j
  14. }
  15. row[i] = num;
  16. }
  17.  
  18. int mask_all = (1 << n) - 1; // 用于截断低 n 位的掩码
  19. int ans = INT_MAX;
  20.  
  21. // 枚举第一行的翻转状态
  22. for (int mask = 0; mask < (1 << n); ++mask) {
  23. int pre2 = 0; // 上上行
  24. int pre1 = mask; // 上一行,初始为第一行
  25. int cost = __builtin_popcount(mask); // 主动翻转的代价
  26. bool valid = true;
  27.  
  28. // 递推计算第 1 行到第 n-1 行(0-based 索引)
  29. for (int i = 1; i < n; ++i) {
  30. // 通过位运算一次性计算当前行的翻转状态
  31. int cur = (row[i - 1] ^ pre1 ^ pre2 ^ (pre1 << 1) ^ (pre1 >> 1)) & mask_all;
  32. cost += __builtin_popcount(cur);
  33. if (cost >= ans) { // 剪枝:当前代价已不小于已知最优解
  34. valid = false;
  35. break;
  36. }
  37. pre2 = pre1;
  38. pre1 = cur;
  39. }
  40. if (!valid) continue;
  41.  
  42. // 验证最后一行是否满足全0条件
  43. int val = (row[n - 1] ^ pre1 ^ pre2 ^ (pre1 << 1) ^ (pre1 >> 1)) & mask_all;
  44. if (val == 0) {
  45. ans = min(ans, cost);
  46. }
  47. }
  48.  
  49. if (ans == INT_MAX) cout << -1 << endl;
  50. else cout << ans << endl;
  51.  
  52. return 0;
  53. }
Success #stdin #stdout 0s 5304KB
stdin
3
1 1 1
1 1 1
1 1 1
stdout
4