zoj 1217

非常经典的题目 八数码问题 不能不AC的题

这道题学了不少东西 试了最土的单向BFS直接TLE 然后上网看代码 改了双向的BFS 6000ms+ 过了

关于这道题的判重也是遇到了不少困难,一开始想把状态当成1个整数,把x当成0,结果还真去写了,突然发现数组根本不能开这么大

于是想了想其实这状态总数也才 9!  = 362880 就想只用这个数量的数组储存状态 把整个序列当做一个整数 我只要知道这个数在所有排列里第几个大就可以了 后来查了下这叫康托展开 转一段介绍

这里我们介绍一种可以将全排列的一种表示为“第几个排列”的方法——康托展开。

首先看几个康托展开的实例(9的全排列):

1 2 3 4 5 6 7 8 9——展开为 0。

1 2 3 4 5 6 7 9 8——展开为 1。

1 2 3 4 5 6 8 7 9——展开为 2。

由这些最开始的方法我们可以发现一个规律:从第一个数开始,依次判断判断这些数是当前没有出现过的数的第几个(由0开始),记为a1, a2, ... ,a(n - 1)。不难发现如1 2 3 4 5 6 8 7 9,由1至6都是当前没有出现过的第0个数,而8是7,8,9中的第1个(由0开始),9是7,9中的第1个,7是第0个。故a1 = a2 = ... = a6 = 0,a7 = 1,a8 = 1,a9 = 0。

之后排列数(康托展开的值)等于

a1 * (n - 1)! + a2 * (n - 2)! + ... + ak * (n - k)! + ... + an * 0!

再举几个例子:

3 5 7 4 1 2 9 6 8——展开为 98884。

5 6 7 8 1 2 3 4 9——展开为 184800。

至于双向BFS 就是知道初始和目标状态的情况下,就可以正向反向一起广搜,找到一个另一方向已搜到过的节点就得到解了

一般来讲每次选择队列中节点比较少的一边来进行下一次搜索。

双向BFS的代码

 

后来在网上查到了A*算法 是一种启发式搜索算法 因为这道题并不要求最优解,所以还是速度重要 空间上的开销的话 已经算出只有9!个

状态 所以可以用A*算法 启发式算法对我来说还是太复杂了 其实并搞不懂 这道题参考了网上的介绍和代码 写了一个A* 速度确实快的多

下面摘一段一个大牛对8数码问题的研究报告 

启发式搜索是在路径搜索问题中很实用的搜索方式,通过设计一个好的启发式函数来计算状态的优先级,优先考虑优先级高的状态,可以提早搜索到达目标态的时间。A*是一种启发式搜索的,他的启发式函数f ' ()=g' () + h' () 能够应用到八数码问题中来。
        g' () ----- 从起始状态到当前状态的实际代价g*()的估计值,g' () >= g*()
        h' () ----- 从当前状态到目标状态的实际代价h*()的估计值,h' () <= h*()
注意两个限制条件:
        (1)h' () <= h*()  (2)任意状态的f '()值必须大于其父状态的f '()值,即f '()单调递增。

        其中,g' () 是搜索的深度, h' () 则是一个估计函数,用以估计当前态到目标态可能的步数。解八数码问题时一般有两种估计函数。比较简单的是difference ( Status a,  Status b ), 其返回值是a 和b状态各位置上数字不同的次数。另一种比较经典的是曼哈顿距离   manhattan ( Status a, Status b ),其返回的是各个数字从a的位置到b的位置的距离(见例子)。

例如状态 1 3 7 2 4 6 8 5 2 和状态 1 2 3 4 5 6 7 8 9 的difference 是5(不含空格)。而他的manhattan 距离是:
1 (7d一次) + 1 (2u一次) + 2 (4l两次) + 3 (6r两次u一次) + 2 (5u一次l一次) = 9
单个数字的manhattan应该小于5,因为对角的距离才4,若大于4则说明计算有误。

        无论是difference还是manhattan,估计为越小越接近END,所以优先级高。
        在计算difference和manhattan时,推荐都将空格忽略,因为在difference中空格可有可无,对整体搜索影响不大。

        本文后面的实现将使用manhattan 不计空格的方法。其实,每移动一步,不计空格,相当于移动一个数字。如果每次移动都是完美的,即把一个数字归位,那么START态到END态的距离就是manhattan。反过来说,manhattan是START到END态的至少走的步数。
        回到f '()=g' ()+ h' (),其实广度搜索是h' ()=0的一种启发式搜索的特例,而深度搜索是   f ' ()=0 的一般搜索。h' ()对于优化搜索速度有很重要的作用。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ray58750034/archive/2006/02/15/599897.aspx

我用的估计函数是Manhattan距离

下面是代码 我的代码效率太低 双向广搜和A* 都没有达到理想的效果 只是AC了1217 运行时间比大牛们用一样的算法慢很多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值