3X3拼图的可解性

几个定义:

1、逆序数
     例如: 1 2 3 5 4,逆序数有1对,54
                5 4 3 2 1,逆序数有10对,54,53,52,51,43,42,41,32,31,21

2、奇排列偶排列
     一个排列,逆序数总数为奇数则为奇排列,否则为偶排列。
     例如上面的两个排列:12354位奇排列,54321为偶排列。

3、关于奇排列和偶排列的定理
      偶排列任意交换两个数形成奇排列,奇排列任意交换两个数形成偶排列。



拼图的可解性(一个随机拼图一半无解):

     假设3*3的拼图为0-8的数字,0表示可以交换的空白块,123456780为最终状态。显然123456780为偶排列,0所在的位置为偶位置。
     那么,有两种方式可以判断拼图是否可解:

     (1) 判断整个序列是奇排列还是偶排列,再判断0的位置是奇位置还是偶位置,如果前两者的奇偶性相同则有解。
       说明:初始状态123456870为奇排列,0所在的位置为偶位置。每次移动必然导致0的位置奇偶性和整个排列的奇偶性变化一次,因此无论如何都不可能移动到123456780整个最终排列和0的位置都为偶的状态。

     (2) 序列里面排除空白块0,判断序列是奇排列还是偶排列。如果是偶排列,则可以完成。
      说明:因为排除0,所以0每次和附近的交换都不影响奇偶性,所以最初为奇排列,怎么都移动不成偶排列。


伪代码(c):

/* 第一种实现 */

map[9];
cnt = 0;

/* 计算逆序数总数 */
for(i = 0; i < 8; i++)
     for(j = i + 1; j < 9; j++)
     {
          if(map[i] > map[j])
               cnt++;
     }

/* 判断空白块0的位置 */
for(i = 0; i < 9; i++)
{
     if(map[i] == 0)
          break;
}

if(cnt % 2 != i % 2)     //奇偶性不同则无解
{
     //无解
}

/* 第二种实现 */

map[9];
cnt = 0;

/* 计算逆序数总数 */
for(i = 0; i < 8; i++)
     for(j = i + 1; j < 9; j++)
     {
          if(map[i] > map[j] && map[j] != 0)     //排除空白块0
               cnt++;
     }

if(cnt % 2)     //奇排列则无解
{
     //无解
}


怎么把无解的拼图变为有解?

     任意交换两个 非空白块的位置就能让拼图从无解变为有解。

4X4拼图也一样吗?
     不一样,从第一种方法的分析可知。空白块的移动会导致奇偶位置变化一次,因为3X3的奇偶位置如下
     0  1  0
     1  0  1          
     0  1  0
     而4X4的不一样了,如下
     0  1  0  1
     0  1  0  1
     0  1  0  1
     0  1  0  1
     这样,上下移动,空白块位置的奇偶性不变,会导致需要重新分析可解性。



参考: http://www.guokr.com/question/579400/

你可能感兴趣的:(算法)