HihoCoder1312
题目描述:
解答:
·规则:
首先简要说明游戏规则。
游戏的棋局如下:
九宫格中放置8个标有不同数字的棋子,其中一个位置为空,通过移动棋子,使得数字有序排列,则游戏完成,如下:
在移动的过程中,只有和空白位置相邻的棋子才可以移动,并仅可以移动到空白位置。下面的例子中可以通过6次移动完成游戏:
以上为游戏规则。
·编码:
本题的思路还是比较简单的。通过dijkstra算法,计算每个棋盘状态到最终状态的最短路径即可。这里的“最短路径”定义为最少的移动的次数。那么首先的问题就是以某种方式记录棋局的状态。方法如下:
假设空白位置记为数字9,那么不同的棋局的数目为:9!= 362880种。如果以字典序将所有的排列方式排序的话,那么每个排列结果就会有唯一的一个编号。因此,编号为1的排列为:123456789,编号为362880的排列为:987654321。所以,目前的问题是给出一个排列,找出它在字典序中的编号。这个问题可以采用一种叫做“康托展开”的方法来求解,方法如下:
对于某一个排列:s[1,2,...9], 定义序列a[1,2,...,9],其中a[i]表示序列s[i+1, i+2, ... 9]中比a[i]小的数值的个数, 例如,排列 9 1 2 3 6 4 7 8 5 对应的a[i] 序列为:8 0 0 2 0 1 0 0。
在给出a[i]序列后,排列s对应的序号为:
X = a[1] * (9 - 1)! + a[2] * (9 - 2)! + ... + a[9] * (9 - 9)!
游戏的目标结果为:1 2 3 4 5 6 7 8 9,对应的序号为1。
·解码:
在知道编码方法后,我们还需要知道如何在给定编号X的情况下,找到对应的排列结果。这个过程是康托展开的逆过程,可以称为“逆康托展开”。方法如下:
① 用