A*算法在8数码(滑块拼图)问题中的应用理解

关于A*算法,有些资料讲解很不错,如

https://blog.csdn.net/hitwhylz/article/details/23089415

https://www.jianshu.com/p/a3951ce7574d

在上篇滑块拼图的问题

https://blog.csdn.net/aaajj/article/details/100375751

处理后,我发现,从广度优先搜索(BFS)的角度去理解A*算法非常清晰易懂。

A*可以看成是对广度优先搜索的一种改进,在BFS中,使用队列保存每层中的节点,

从队列头部取出节点进行检查的时候,再将其子节点都放到队列的尾部,这样实现按照层次查找的效果。

 

A*对节点队列进行了处理,总是优先对估值低(最优)的节点进行处理,这有些类似动态规划,这样就避免了BFS搜索的盲目性。

体现出了“以正合,以奇胜”的哲学思想

 

使用一个表(队列)来存放待检查的节点

 

 

 

 

Open表可以使用一个有序链表结构来实现,主要有添加和删除操作,如

 

//test A*

void addNode(PNode* head, PNode* data)

{

    while (head->next != NULL)

    {

        PNode* t = head->next;

        //already in the list

        if (t == data)

        {

            return;

        }

 

        if (data->f < t->f)

        {

            data->next = t;

            head->next = data;

            return;

        }

        head = head->next;

    }

 

    if (head->next == NULL)

    {

        head->next = data;

        data->next = NULL;

    }

}

 

void rmNode(PNode* head, PNode* data)

{

    while (head->next != NULL)

    {

        PNode* t = head->next;

        if (t == data)

        {

            head->next = t->next;

            delete t;

            return;

        }

        head = head->next;

    }

}

 

Close表由于需要经常用来查找,可以使用map来实现

 

估值函数h一般要在一定程度上表现出各节点间距离的差异。

对于8数码以及滑块拼图问题,估值函数h可以简单的用不匹配的滑块数量来表示,如

目标:

1 2 3

4 5 6

7 8 0

 

状态A

1 2 3

4 0 5

7 8 6

的h值为3,有3个位置不匹配,A可以通过滑动0到达状态B和C

B:(h值为2)

1 2 3

4 5 0

7 8 6

 

C:(h值为4)

1 2 3

0 4 5

7 8 6

显然,从状态A进行移动选择的时候,选择h值为2的B状态更好,事实也确实如此。

 

h函数也可以稍微复杂点的绝对距离和来表示

以状态A为例

1 2 3

4 0 5

7 8 6

计算每个滑块分别单独放好的步数,对其求和来作为h估值

这里,h=h(1) +h(2)+h(3)+h(4)+h(5)+h(6)+h(7)+h(8)+h(0)

=0   + 0  +0   + 0 + 1+  1   + 0   + 0+ 2

=4

我们也可以不把空白块0计算进去,这要看对h函数的具体设计。

 

 

 

发布了336 篇原创文章 · 获赞 13 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/aaajj/article/details/100603536