1.题意
有一个4*4的(+,-)符号矩阵,改变一个元素的符号,所在行列都反转最少次数,让所有符号变成 - 号 并打印出符号位置;
2,思路
- 翻转的执行先后序列不影响结果;
- 每个点最多一次,有翻和不翻的选择;
- 0-0xFFFF表示矩阵状态,看最后状态是不是0x3FFFF,我们用0代表+,1代表-;
3,代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int chess, step;
bool flag = false;
int map[5][5];
int xx[20], yy[20];//记录路径
bool panduan(){//判断函数
return chess == 0XFFFF ? true : false;//全部为- 时 就是16个1 的二进制 0xFFFF;
}
void fanzhuan(int bit){//翻转函数,bit为我们要对第bit个棋子进行翻转,为了方便计算坐标(0~15)表示每个棋子
chess = chess ^ (1 << bit);
//自身翻转,比如有4个棋子现在是0110, 翻转第2个棋子, chess^(1<<1) 0110^10=0100
int tx = bit / 4;//通过bit 计算在矩阵中第bit个坐标
int ty = bit % 4;
for(int i = 0; i < 4; i++){
chess = chess ^ (1 << (tx * 4 + i));// 同一行
}
for(int i = 0; i < 4; i++){
chess = chess ^ (1 << (i * 4 + ty));// 同一列
}
return ;
}
void dfs(int bit, int count){
if(count == step){//当前步数到达了我们计划要的步数
flag = panduan();//判断是否全 -
return;
}
if(flag || bit > 15) return ;//bit >15 超过16个或者已经找到了答案
xx[count] = bit / 4;//记录count步的位置,count可以被覆盖的
yy[count] = bit % 4;
fanzhuan(bit);//翻转bit位
dfs(bit + 1, count + 1);
fanzhuan(bit);//不翻转 翻两次就变回来了嘛,相当于回溯
dfs(bit + 1, count);//不翻就不加1
}
int main(){
char str;
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
cin >> str;
if(str == '-'){//'-' 为开
chess = chess ^ (1 << ((i * 4) + j));//二进制表示状态
}
}
}
for(step = 0; step <= 16; step++){
dfs(0, 0);//最少步数,最多16或者没有解,从0步开始试探,就可以保证最少步数
if(flag)
break;
}
cout << step << endl;
for(int i = 0; i < step; i++){
cout << xx[i] + 1 <<" " << yy[i] + 1 << endl;
}
}