http://poj.org/problem?id=1077
八数码问题:
由1,2,3,4,5,6,7,8,x组成一个3*3的矩阵,如
1 2 3
4 x 5
6 7 8
其中x可与其上,下,左,右相邻的元素互换,
现问从给出状态出发到达以下状态:
1 2 3
4 5 6
7 8 x
需要对x进行怎样的位移操作,输出x的最少位移信息,
若状态不可达,输出unsolvable
分析:
1.一个很容易的想法,即BFS,
2.用康托展开将每个状态转化为整数,即可略过已访问点
3.再用优先队列加以优化
4.其实可以用A*加以优化,f(x) = g(x)+h(x),h(x)为当前状态中x所在位置到右下角位置的哈密尔顿距离(不过实际中没遇到)
5.如果是单case的话,用以上即可水过,
但若是多case,复杂度会过高,超时。
6.解决多case的方法是,在预处理中从目标状态出发BFS,记录所有可达状态信息。
这样,对于输入的任何一种状态,便可直接输出答案(又邪恶了吧。。)
PS:
问题在BFS过程略过已搜索过的状态
纠结了很久之后,终于还是不忍去网上搜了一下,
呵呵,居然让我发现还有康托展开这么个好东东!
关于康托展开,百度百科上说得还是比较清楚的:http://baike.baidu.com/view/437641.htm
简单说一下:
将x抽象为数字9,对于每个状态,可映射为{1,2,3,4,5,6,7,8,9}的一个排列。
根据康托展开,即将具体的排列转化为一个数字,即可保存其状态
这个该死的康托,还是用了一定的时间去搞的,可惜,我只知道怎样把一个排列变成数字,把数字变成排列是怎么也搞不来,
所以,偷偷小懒,干脆把数组扔进了节点里,邪恶了。。。
因为POJ上是单case的,所以果断从给出的状态BFS直到搜到最终状态为止,就这样邪恶的水过。。
ZOJ和HDU貌似很是不给面子,多case,果断超时。。。。
回来继续研究,赫,不让我怎么搞,我就倒着搜呗,于是想到了在预处理中从目标点BFS一次,记录下所有可达状态,O(∩_∩)O哈,就这么水水地又过了。。
Code BFS:
IDA*
很巧妙的方法,从人家http://www.cnblogs.com/liyongmou/archive/2010/07/19/1780861.html那里偷来的,个人觉得很不错,也在这里贴一下,(*^__^*) 嘻嘻……
IDA*