十字翻转棋的解法(高斯消元法)

来源:互联网 发布:mcs-51单片机寻址方式 编辑:程序博客网 时间:2024/04/29 05:51

翻转棋带给我的启发

——布尔方程&高斯消元法

今天上午上软件工程需求建模课,觉得乏味,开始玩起游戏。无意间看到徐浦手机上的翻转棋游戏,于是便一发不可收拾的去思考最佳解法。

翻转棋游戏,是一类智益游戏: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)…x(20)},猜测方程有唯一解。然后求解的时候需要变形。

x(1)^x(2)^x(5)^s(1)=0 ==> x(1)^x(2)^x(5)=s(1)

然后,对于方程组,由于只含有异或操作,于是可以用高斯消元法求解。

比如说:

x(1)^x(2)^x(5)=a (1)

x(1)^x(2) =b (2)

==>对(1)(2)取异或得到(3)

x(1)^x(2)^x(5) ^ x(1)^x(2)=x(5)=a^b (3)

这个和高斯消元法的思路非常像,于是问题就搞定了~~~

分析一下解方程的时间复杂度:高斯消元法的复杂度,O(n^2),比原来的暴力要快。