8数码问题

本文介绍了8数码问题的解决方案,利用图来表示所有可能的情况,并通过两个标记数组防止路径重复。核心算法包括最小堆实现,用于A*搜索过程中节点的选取。此外,还探讨了深度优先搜索和广度优先搜索在解决此类问题中的应用。
摘要由CSDN通过智能技术生成
人工智能的经典题目,8数码问题

问题隐含的数学原理
这个问题其实涉及到数学中群论。目标状态问题可以归结为一个置换群的问题,一个任意的状态A最终如果能够达到目标状态F,那么我们可以说置换群的个数为1,如果只有50%的可能性,那么这个置换群的个数就是2了。置换群内部的状态可以互相转换,但是却不可能有A群中的状态转向B群中的状态互相转换的情形发生。九宫格的问题其实是一个奇偶置换群的实例,该群无论如何置换奇偶性都不变,所以如果开局和目标的奇偶性相同,就一定有解(因为经过有限次的置换一定循环),如果奇偶性不同,一定无解。

n*n的方格中放入1,2,3,…,n-1及一个空格,在任何一种状态A下,  
定义:f(i)=k,表示i放在第k个格子中,k按照从左至右,从上到下排序;  
定义:g(i,j)=1, 如果(f(i)-f(j))(i-j)<0;否则为0;
定义:F(A)=∑ g(i,j),对所有i,j求和(这里i
针对图1,其目标F(End)=0,其初始F(Begin)=12(f(1)=1 f(2)=9 f(3)=3 f(4)=4 f(5)=8 f(6)=2 f(7)=7 f(8)=5),其奇偶性相同,故有解。利用F函数可以解决所有n为奇数的情况。
比如n=3,因为移动空格只有2种方式:在同行中移动不改变F值,在不同行中移动F值+2,-2或不变,故初始和末态的状态不会发生改变。

问题隐含的人工智能原理
在数学上,我们虽然完美解决了问题是否存在解决方案的问题,但是实际上,我们需要实现这个方案的具体内容,即在存在解的情况下,如何移动最少的步数使其达到目标状态。人工智能的启发式搜索算法在这里派上了用场。
所谓的启发式搜索就是对于许多应用过程,可以找到领域特有的知识来指导搜索过程,以提高工作效率,而这些知识称为启发式知识。
我们先给出状态空间搜索的概念,状态空间搜索,就是将问题求解过程表现为从初始状态到目标状态寻找这个路径的过程,就是在解一个问题时,找到一条解题的过程可以从求解的开始到问题的结果。由于求解问题的过程中分枝有很多,主要是求解过程中求解条件的不确定性,不完备性造成的,使得求解的路径很多这就构成了一个图,我们说这个图就是状态空间。问题的求解实际上就是在这个图中找到一条路径可以从开始到结果。
这个寻找的过程就是状态空间搜索。常用的状态空间搜索有深度优先和广度优先。广度优先是从初始状态一层一层向下找,直到找到目标为止。深度优先是按照一定的顺序前查找完一个分支,再查找另一个分支,以至找到目标为止。这两种算法在数据结构书中都有描述,可以参看这些书得到更详细的解释。
前面说的广度和深度优先搜索有一个很大的缺陷就是他们都是在一个给定的状态空间中穷举。这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不预测的情况下就不可取了。他的效率实在太低,甚至不可完成。
在这里就要用到启发式搜索了。启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无畏的搜索路径,提到了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。我们先看看估价是如何表示的。
启发中的估价是用估价函数表示的,如:f(n) = g(n) + h(n),其中f(n)是节点n的估价函数,g(n)实在状态空间中从初始节点到n节点的实际代价,h(n)是从n到目标节点最佳路径的估计代价。
对于这个九宫格游戏,我们采用如下的评价函数,f(n) = d(n) + h(n),其中d(n)为当前状态从初始状态开始移动的步数,h(n)计算当前状态与目标状态相比错位的个数。搜索过程总是往f(n)最小的分枝方向进行,以便快速达到最终状态。

解决问题的思路

 

8数码问题,相当于一个9个数字的全排列。则它总共有9362880种情况。

我们使用图来存放的话,则需要362880个节点。

 

该问题化为:

则任选一个节点,找出走向目标节点的路径。

 

要防止路径重复:

需要建立两个标记数组

bool open_list[MAX];

bool close_list[MAX];

来标记已经走过的路径。


 关于我的代码中的映射(解码函数):

增序排列  大小为0

减序排列  大小为9-1 362879

其他的任何排列的值,都在其间且有唯一的一个值 ,所以设计改映射。换成其他的映射也可以,而这个映射比较小。 


以下是C++源码:


MinHeap的模板:

#ifndef MINHEAP_H

#define MINHEAP_H

#include

#include

using namespace std;

const int DefaultSize = 362885;


template class MinHeap{// T为关键码的数据类型,Item为记录的结构类型

public:

MinHeap(int sz = DefaultSize);//构造函数:建立空堆

MinHeap(Item arr[], int n); //构造函数:通过一个数组建堆

~MinHeap(){

delete []heap;

}

bool Insert(const Item &x);

bool RemoveMin(Item &x);

bool IsEmpty()const{

return currentSize == 0;

}

bool IsFull()const{

return currentSize == maxHeapSize;

}

void MakeEmpty(){

currentSize = 0;

}

private: 

Item *heap; //存放最小堆中元素的数组

int currentSize; //最小堆中当前元素个数

int maxHeapSize; //最小堆最多允许元素个数

void siftDown(int start, int m);//从start到m下滑调整成为最小堆

void siftUp(int start); //从start到0上滑调整成为最小堆

};


// 构造函数:建立空堆

template MinHeap< Item>::MinHeap(int sz){

maxHeapSize = (DefaultSize < sz) ? sz : DefaultSize;

heap = new Item[maxHeapSize];

assert(heap);

currentSize = 0;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值