intmain() { for (int i = 0; i < N; i ++ )// change每个位置二进制表示将哪些位置取反 //对照着solution1的turn_all & turn_one函数就比较好理解啦 for (int j = 0; j < N; j ++ ) { for (int k = 0; k < N; k ++ ) change[i][j] += (1 << get(i, k)) + (1 << get(k, j)); change[i][j] -= 1 << get(i, j); }
int state = 0;// state用于存放所有把手的当前状态 for (int i = 0; i < N; i ++ ) { string line; cin >> line; for (int j = 0; j < N; j ++ ) if (line[j] == '+') state += 1 << get(i, j); }
vector<PII> path; for (int i = 0; i < 1 << 16; i ++ )// 枚举对把手的所有操作 { int now = state; vector<PII> temp; for (int j = 0; j < 16; j ++ ) if (i >> j & 1) // 求i的第j位数字 { int x = j / 4, y = j % 4; now ^= change[x][y]; // 对now的把手进行反转,异或取反 temp.push_back({x, y}); } // 判断解存在且是最优解 if (!now && (path.empty() || path.size() > temp.size())) path = temp; }
// dalao的优化版本,比solution1快了近10倍 #include<iostream> #include<algorithm> #include<vector> usingnamespacestd; #define pu push_back #define pop pop_back #define fi first #define se second typedefpair<int,int> PII; int g[5][5]; vector<PII> ans,tmp;
voidturn(int x,int y){ for (int i = 1;i <= 4;i ++) g[x][i] = !g[x][i],g[i][y] = !g[i][y]; }
voiddfs(int x,int y){ // 如果说所有的把手都操作完了就看看冰箱能否打开 if (x == 4 && y == 5){ bool flag = true; for (int i = 1;i <= 4 && flag;i ++){ for (int j = 1;j <= 4 && flag;j ++){ if (g[i][j]) flag = false; } }
if (flag){// 判断是否最优解 if (ans.empty() || ans.size() < tmp.size()) ans = tmp; } return;// 递归结束千万记得退出 } // 判断边界,如果y出界了就往下一行移动 if (y == 5) x ++,y = 1; // 不翻转 dfs(x,y+1); // 翻转 g[x][y] = !g[x][y]; turn(x,y); tmp.pu({x,y}); dfs(x,y+1); g[x][y] = !g[x][y];// 恢复现场,关键所在 turn(x,y); tmp.pop(); }