对于输入样例,是一个4*4的矩阵,在这里我们用"1"表示“+”,“0”表示“-”。
对于终态是一个全为0的矩阵。由于每对一个开关操作,对应的行和列都会发生改变,由题可得,我们做的就是通过若干次开关操作构建一条从初态到终态的路线。
以示例为例,输出了(1,1)->(1,3)->(1,4)->(4,1)->(4,3)->(4,4),依次对上述位置的开关进行了操作。我们用二进制来表示上述方案即为:
0 1 1 1
0 0 0 0
0 0 0 0
0 1 1 1
按题意从上到下,从左到右打开:
1110 0000 0000 1110
这样我们就将一种方案通过二进制的方式表示了,我们将初态以16位二进制表示得 0010 0000 0000 0010(从上到下,从左到右)
对于16个把手,一共有216种排列组合能够使得初态到达不同的终态,我们需要的是其中能够使得初态变为全0的方案且该方案的二进制表示中1的数量尽可能少。由于对同一个位置执行两次操作是没有意义的,所以每一个开关只会执行一次。
我们可以枚举这216种可能,为了符合从上到下,从左到右搜索,对于每一个单独的方案,我们从地位到高位一次遍历其中的“1”,每找到一个就执行开关操作,我们用k表示位置,则每一个开关的位置变化可以表示为
x=i/4,y=i%4;
i从0遍历到16,符合从上到下,从左到右搜索。
同时我们每执行一次开关操作需要更新初态的状态到下一个状态,因为对应开关的行和列的数都会发生改变,即取反。我们知道对一个二进制数的某一位取反,只需要将该位异或一个1即可。这里我们可以计算一个矩阵用于存储对每一个开关操作后的数值,即取反后的数值。
以(1,1)为例,执行后
0 0 0 0 —》 0 1 0 0
0 0 0 0 —》 1 1 1 1
0 0 0 0 —》 0 1 0 0
0 0 0 0 —》 0 1 0 0
二进制表示:
0010 0010 1111 0010
将其与初态进行异或操作:
0010 0010 1111 0010 ^ 0010 0000 0000 0010
可以得到下一个状态。
思路总结:
1.将初态以二进制表示,用一个整数来存储
2.记录对每个位置执行开关操作后行和列取反后得数值,该数用于使上一个状态到下一个状态。
3.枚举216种可能,遍历每种可能中的1的个数,执行开关操作,记录该操作的位置,并进入下一个状态
4.判断终态是否为全0,以及目前的方案是否是最少,若不是则更新,由于我们是从上到下,从左到右搜索,最先记录的方案是符合该顺序的,即时后面有相同长度,其他顺序的方案,我们也不会更新。
代码
#include<iostream>
#include<string>
#include<queue>
//#include<bitset>
using namespace std;
int main()
{
int state=0;
int x,y;//保存编号位置
//把输入的初始状态通过位运算转化为整数
for(int i=0;i<4;i++)
{
string line;
cin>>line;
for(int j=0;j<4;j++)
{
if(line[j]=='+')
state+=1<<(4*i+j);
}
}
//创建一个数组存储每一位进行操作后的变化,
int change[4][4]={0};
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
for(int k=0;k<4;k++)
{
change[i][j]+=1<<(4*i+k);//每一行的变化
change[i][j]+=1<<(4*k+j);//每一列的变化
}
change[i][j]-=1<<(4*i+j);//减去第i,j位置重复多算一次的值。
}
//cout<<bitset<16>(change[1][1])<<endl;
}
//枚举2^16种方案,每种方案是一个16位的二进制数,里面的1代表操作的位置
queue<int> Q;//
for(int i=0;i<(1<<16);i++)
{
int now=state;
queue<int> q;
for(int j=0;j<16;j++)
{
if(i>>j&1)
{
x=j/4,y=j%4;//记录1的编号位置
now^=change[x][y];//更新点击位置(x,y)后的状态
q.push(x);
q.push(y);
}
}
if(!now && (Q.empty() || Q.size()>q.size()))
Q=q;
}
cout<<Q.size()/2<<endl;
while(!Q.empty())
{
x=Q.front();
Q.pop();
y=Q.front();
Q.pop();
cout<<x+1<<" "<<y+1<<endl;
}
return 0;
}