翻转棋带给我的启发
——布尔方程&高斯消元法
今天上午上软件工程需求建模课,觉得乏味,开始玩起游戏。无意间看到徐浦手机上的翻转棋游戏,于是便一发不可收拾的去思考最佳解法。
翻转棋游戏,是一类智益游戏:5×4的方格,每个格子黑色或者红色,如下图
点击某一个方格,那么此格子的上下左右格子以及它本身 颜色都取反。于是,问怎么点击才可以使得所有的格子都变成红色?
在纸上模拟了好几次,发现存在最小的点击次数。因为某个格子点一次和点3次效果一样,于是开始思考这个问题的解法。最典型的当然是暴力,20个格子,时间复杂度O(2^n)。显然格子再多一点就不靠谱。既然格子只有两个状态,那么,所有的运算都是布尔运算。而且考虑到,在一个格子上点击两次其实没变化,于是可以做出推断,最多只需要点击20次就可以得出所需要的状态。那么如何做呢?
我的方法是:用x(i)表示第i个方格是否需要点击。X(i)只取0或1,取1代表这个格子需要点击,取0则不需要点击。问题转换为如何求解x向量。现在我们需要加约束,因为所有格子都需要变成红色。不妨假设,红色的状态为0,黑色的状态为1。那么就是点击某些格子,让所有的x(i)变成0。
接下来列方程:
假设格子的原始状态为s(i),对于第一个方格:x(1)^x(2)^x(5)^s(1)=0。等式的意思就是说,对于第一个格子,如果要使它变成0,那么只能是点击1、2、5三个方格起作用。而如果x(1)取1,那么方格状态取反,刚好用异或操作(^)就可以解决;如果x(1)取0,异或0没有什么影响。
于是对于所有的格子,我们都列出一个布尔方程。二十个方程对应二十个变量{x(1