终于被我水过了,哈哈,4640MS,真的是卡时间啊。。,先用这个水水,还没搞清楚什么地方耗太多的时间,别人好像也没用多少时间的啊。之后看了下A*算法,时间上的消耗就减少了很多。
题意:
给定一个序列,由1~8数字和字母x组成,表示的是一个3*3的矩形。每次操作x都能与相邻的数字交换,问如何操作才能使得序列为{1,2,3,4,5,6,7,8,x}。
题解:
1)双向BFS
这题需要特判无法变换到得情况,我们发现每次变换8个数字的逆序数奇偶性都是不变的,所以找出给定的序列的逆序数可以特判不存在的情况。
之后要了解下康托展开(一开始直接map,死的惨惨的),这个是为了哈希用的,就是压缩的排列,使得其变为第几个排列,那样就容易哈希了:对于14032,在排列中排第几个?是1*4!+3*3!+0*2!+1*1!+0*0!,为什么呢,类似于数位dp,第一位比1小的只有1个,后面可以随意排列,既4!种;接着确定第一位为1,第二位比4小的有4个,但1已经用过了,就只有3*3!种情况;接着确定前两位是14...以此类推。
通过康托展开,我们将x=0,那样所有的排列都可以转换成0到9!了,360000左右各值,很容易用数组哈希。
之后是双向BFS,跟单BFS用的一样,从开头和终点一起开始BFS,直到两个BFS相遇,就是最短的路程了。这样可以缩短很长的时间,why?例如一个迷宫,我们假设没有边界,没有墙的空地,单BFS需要4^n时间,那双向BFS就是4^(n/2)*2,缩短了很多。
2)A*算法
A*算法是一种求最短路径的算法,会添加一个评估函数h(n),以减少时间的消耗;BFS是一种特殊的A*算法,h(n)=0。
拓展方式跟BFS类似,不过采用优先队列,以f值小的优先(f=g+h,g为实际到这点的消耗,h为预测到目标点的消耗)。若h<=n(n为实际这点到目标点的消耗),必定存在最优解;若h>n则不一定存在最优解。所以h值越接近n值越好,但不要超过。
具体解释:A*算法-百度百科,A*算法入门-博客园
代码:
1.双向BFS
#include
#include
#include
#include
#include
#include
#include
#include
2.A*算法:
#include
#include
#include
#include
#include
#include
#include
#include