8数码问题的广搜在网上可以找到代码,广搜一般可以找到最优解,但是深搜不一定能找到最优解。一般的深搜多是指定最大递归深度的深搜,一般情况下,问题解的深度很难确定。因此深搜会出现三种情况,一是找到最优解,二是在迭代深度内找不到解,三是找到解但不是最优解。第一种情况自然是最好的,不过较经常出现的是第三种,在指定迭代深度不适当的时候也会出现第二种情况。
在迭代深度内找不到解是最糟糕的一种情况,对这个问题没有什么好的解决办法。有时候我们可以用试凑法,多次测试来找到一个比较好的递归深度。对同一输入在不同迭代深度范围内的比较如下:
输入数据
6 2 8
0 1 4
7 3 5
对于上面的测试数据,广搜的搜索深度为17,是最优的结果。下面的表格中列出了深搜的搜索深度,可以看到深搜的搜索深度不是固定的。
最大深度 | 17 | 20 | 30 | 100 |
求得解时深度 | 17 | 19 | 29 | 97 |
在下面给出的8数码问题的深度求解算法中,采用非递归的深度优先搜索,并且给出了一个较合理的递归深度。对于代码中的hash值得求取,可能有好些朋友看不大懂,这里我简单讲解一些为什么这样计算hash值。
我们设 hash = a * 8! + b * 7! + c * 6! + d * 5! + e * 4! + f * 3! + g * 2! + h * 1! + i * 0! , 其中 a - i 分别是 0 - 8 的逆序数。到了这里,知道逆序数的朋友可以一下子就明白了。我们可以很容易的证明 a <= 8 , b < 8 , c < 7 ...... b < 8 则一定有 b * 7! < 8! 我们可以得到,如果 hash > 8! ( 即 (hash / 8! ) != 0 ) 则一定有 a != 0 ,且 hash / 8! = a,依次类推,我们可以证明 (hash % 8! ) / 7! = b ......这就是一个映射的过程,这个映射可以保证对于一组(a , b , c , d , e , f , g , h , i )一定有唯一的 hash 并且对于 一个 hash 一定有唯一的一组( a , b , c , d , e , f , h , i )相对应。
【EDigital.h】
#pragma once
#include <queue>
using std::queue;
#define HashTableSize 362881
#define DigitalSize 9
#define MaxDeepth 30 //深度优先搜索的最大搜索深度,对有些数据,其最优解可能超过30深度,这时候深搜,程序将不会给出正确结果
class EDigital
{
public:
typedef struct
{
int a[DigitalSize];
}Detail;
private:
typedef struct maps
{
char detail[DigitalSize];
int index; // 记录自己节点在hash表中的位置
char position; // 记录 空格(0)在序列中的位置
}Map,