AcWing
116. 飞行员兄弟
对于每个把手,可以操作,也可以不操作(重复地操作同一个把手无效),一共有$2^16$种操作方案,每一种方案对应16
个把手的操作用一个16
位的二进制数表示,000...000 ~ 111...111
,十进制即0 ~ 65535
. 对于每一种操作方案,枚举二维的把手位置,映射到二进制方案的对应位上,判断其是否为1
(表示操作),是则改变行列状态。注意在每一次操作方案迭代之前要复原数组。
#include <bits/stdc++.h>
using namespace std;
char g[4][5], backup[4][5];
int getoffs(int a, int b){
return 4 * a + b;
}
void turnone(int a, int b){
if(g[a][b] == '+') g[a][b] = '-';
else g[a][b] = '+';
}
void turnall(int a, int b){
for(int i = 0; i <= 3; i++) turnone(i, b);
for(int i = 0; i <= 3; i++) turnone(a, i);
turnone(a, b);
}
int main(){
for(int i = 0; i <= 3; i++) cin >> backup[i];
int res = 17, rop;
for(int i = 0; i <= (1 << 16) - 1; i++){
memcpy(g, backup, sizeof backup);
int ops = 0;
for(int u = 0; u <= 3; u++) for(int v = 0; v <= 3; v++){
int offset = getoffs(u, v);
if(i >> offset & 1){
turnall(u, v);
ops++;
}
}
bool alllt = true;
for(int u = 0; u <= 3; u++) for(int v = 0; v <= 3; v++) if(g[u][v] == '+'){
alllt = false;
break;
}
if(alllt && ops < res) res = ops, rop = i;
}
cout << res << endl;
for(int u = 0; u <= 3; u++) for(int v = 0; v <= 3; v++){
int offset = getoffs(u, v);
if(rop >> offset & 1) cout << u + 1 << ' ' << v + 1 << endl;
}
return 0;
}