八牛过河问题23101
每个人的状态有三种:左岸、船上、右岸。
其实这就是一个状态转移的问题。令1表示在左岸,0表示在右岸,船、警察、犯人、父亲、儿子1、儿子2、母亲、女儿1和女儿2的位置构成一个状态向量,那么就是求解从初始状态向量[1,1,1,1,1,1,1,1,1]到目标状态向量[0,0,0,0,0,0,0,0,0]的状态转移路径。
在求解这个问题的过程中,我利用了异或运算的特性。异或运算(java中操作符为^)的规则是“相同为假(0),相异为真(0)”。异或运算有一个重要的特性,[1, 0]与0异或的结果还是[1, 0],也就是和0做异或操作不会改变原来的值,但是[1,0]与1异或的结果是[0,1],也就是和1做异或操作会改变原来的结果。
由上面介绍的异或操作的特性,我设置的状态转移向量为9维的向量,如果那个人或船要改变位置,则把相应的位置设置为1,其余不改变位置的地方则设为0,例如,初始状态startState=[1,1,1,1,1,1,1,1,1],可以由警察带着犯人一起划船到对岸,那么状态转移向量就是move=[1,1,1,0,0,0,0,0,0],将startState和move对应位置做异或运算就可以得到转移后的状态为newState=[0,0,0,1,1,1,1,1,1]。
如果把每一个状态都看作是一个顶点,转移向量看作是边的化,其实这就是一个图数据,要求解从初始点到目标点的一条可行路径。可以采用深度优先遍历或广度优先遍历,我喜欢用递归来求解,所以其实是采用的深度优先遍历。在每一个状态下,都生成所有可行的状态转移向量,然后将状态与转移向量做异或运算得到新的状态。
左岸右岸
在求解的过程中要注意:1
检查状态是否安全。不安全的话,则不能继续往下搜索。
防止状态循环。如果当前到达的状态已经出现过了,则不能在继续往下搜索,否则会出现状态循环问题的。