飞行兄弟二进制枚举+异或

Posted rstz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了飞行兄弟二进制枚举+异或相关的知识,希望对你有一定的参考价值。

技术图片



看到这题就知道要暴力枚举,然后就用二进制枚举,用整数来表示对应十字架的状态,也就是2的幂次。


  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <vector>
  5 using namespace std;
  6 
  7 int a[5][5];
  8 int change[5][5];
  9 int get(int x, int y){return x * 4 + y;}
 10 int main(){
 11     int state = 0;
 12     for(int i = 0; i < 4; ++ i)
 13         for(int j = 0; j < 4; ++ j){
 14             char c;
 15             cin >> c;
 16             if(c == ‘+‘)
 17                 state += 1 << get(i,j);//这时起始状态
 18         }
 19     for(int i = 0; i < 4; ++ i)//用来存异或后的状态
 20         for(int j = 0; j <4; ++ j){
 21             for(int k = 0; k < 4; ++ k){
 22                 change[i][j] += 1 << get(i, k);
 23                 change[i][j] += 1 << get(k, j);
 24             }
 25             change[i][j] -= 1 << get(i, j);//加了两次减去一次
 26         }
 27     vector<pair<int, int> >res;//存答案
 28     for(int i = 0; i < 1 << 16; ++ i){//枚举状态0101,1表示要打开,0表示补打开
 29         int now = state;
 30         vector<pair<int,int> > path;
 31         for(int j = 0; j < 16; ++ j)
 32             if(i >> j & 1){//取出第j位二进制数
 33                 int x = j / 4, y = j % 4;
 34                 now ^= change[x][y];
 35                 path.push_back({x,y});
 36             }
 37         if(!now && (res.empty()||res.size() > path.size())) res = path;
 38     }
 39     cout << res.size() << endl;
 40     for(auto i : res) cout << i.first + 1 << " " << i.second + 1 << endl;
 41     return 0;
 42 }

以上是关于飞行兄弟二进制枚举+异或的主要内容,如果未能解决你的问题,请参考以下文章

[枚举] aw116. 飞行员兄弟(二维递推+开关问题+二进制枚举)

AcWing 飞行员兄弟 二进制枚举

飞行员兄弟 DFS+枚举

飞行员兄弟

116. 飞行员兄弟

POJ 1222异或高斯消元|二进制状态枚举