A星八数码求解资料讲解

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
}
}
if(flag%2!=0)
return -1;//搜索失败
}
6源程序(采用上述中更高效的第二种估价函数)。
//************************************
//*八数码问题
//************************************
#include<iostream>
A星八数码求解
实验二A*算法实验I
软工1303 201326811825朱镇洋
一、实验目的:
熟悉和掌握启发式搜索的定义、估价函数和算法过程,并利用A*算法求解N数码难题,理解求解流程和搜索顺序。
二、实验原理:
A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。因此,f是根据需要找到一条最小代价路径的观点来估算节点的,所以,可考虑每个节点n的估价函数值为两个分量:从起始节点到节点n的实际代价以及从节点n到达目标节点的估价代价。
5扩展。
稍微改进了给定的算法,给定的算法中时在求解之后才确定是否有解,而其实判断一个八数码是否有解在输入时即可判断出该是否有解。只要将每位上(除了空格)的特定值(此位之前比该数小的个数)相加,如果得数为偶数,那么可以确定最后有解,否则无解。所以可以在每次输入时判断是否有解,而不必在计算完再确定是否有解,这样在算法的时间复杂度上有很大的提升,该段代码如下:
string stack[1000000];//记录搜索中wenku.baidu.com节点
string record[1000000];//从起点开始记录解路径
int father[10000000];//记录该节点的父节点
int top=0;//stack的指针
priority_queue<P> pq;//open表
map<string,bool> mp;//记录该状态是否已经访问过:1访问过,0没有
#include<map>
#include<queue>
#include<algorithm>
#include<string>
using namespace std;
struct P{
int d;//深度g(n)
int w;//不在位数h(n)
int id;//记录该节点的id,用于输出时找到该节点
cur=pq.top();
for(int i=0;i<9;i++)
{
for(int j=0;j<i;j++)
{
if(cur.s[i]=='0'||cur.s[j]=='0')
continue;
else{
if(cur.s[j]<cur.s[i])
flag++;
}
}
}
if(flag%2!=0)
return -1;//搜索失败
而第二种估价函数只要16步即可到达目标状态,也意味着扩展节点和生成节点只有654个,比第一种少了很多:
原因分析:
通过实验结果也说明了估计函数对启发式搜索算法的重要影响,因为第二种估价函数p(n)是节点与目标节点相比所需移动次数的总和,与第一种估价函数w(n)(只考虑错误位数)相比,p(n)不仅考虑了错位信息,还考虑了错位的距离,比w(n)更完美,所以它的执行效率更高。
4启发式算法特点。
启发式搜索算法的基本思想是:定义一个估价函数f,对当前的搜索状态进行评估,找出一个最有希望的节点来扩展。
先定义下面几个函数的含义:
f*(n)=g*(n)+h*(n)式中g*(n)表示从初始节点s到当前节点n的最短路径的耗散值;h*(n)表示从当前节点n到目标节点g的最短路径的耗散值,f*(n)表示从初始节点s经过n到目标节点g的最短路径的耗散值。
估价函数的形式可定义如下式所示:
f(n)=g(n)+h(n)其中n是被评价的当前节点。f(n)、g(n)和h(n)分别表示是对f*(n)、g*(n)和h*(n)3个函数值的估计值。
利用估价函数f(n)=g(n)+h(n)来排列open表节点顺序的图搜索算法称为算法A。在A算法中,如果对所有的x,
h(x)<=h*(x)成立,则称好h(x)为h*(x)的下界,它表示某种偏于保守的估计。采用h*(x)的下界h(x)为启发函数的A算法,称为A*算法。
算法流程图:
3在求解8数码问题的A*算法程序中,设置相同的初始状态和目标状态,针对不同的估价函数,求得问题的解
令初始状态都为:023415687目标状态为:123405678
通过程序运行结果我们可以发现,上述两种估价函数中明显第二种在算法效率上更具优势,第一种估价函数要通过18步才能到达目标状态,通过中间变量记录扩展节点和生成节点有1062个:
int calw(string s)//计算该状态的不在位数h(n)
{
int re=0;
for(int i=0;i<9;i++)
{
re+=abs(s[i]-t[i]);
}
return re;
}
int solve(int& num)//搜索过程
{
P cur;
if(!pq.empty())
{
int flag=0;
三、实验内容:
1问题描述。
八数码问题:在一个3×3的方阵中放入八个数码1、2、3、4、5、6、7、8,其中一个单元格是空的。将任意摆放的数码盘(初始状态)逐步摆成某个指定的数码盘的排列(目标状态):
2设计两种不同的估价函数。
w(n);w表示不在目标位置的节点数
h(n)=d(n)+;d(n)表示深度
p(n);p表示所有点到其目标节点的步数总和
if(!pq.empty())
{
int flag=0;
cur=pq.top();
for(int i=0;i<9;i++)
{
for(int j=0;j<i;j++)
{
if(cur.s[i]=='0'||cur.s[j]=='0')
continue;
else{
if(cur.s[j]<cur.s[i])
flag++;
string s;//状态
friend bool operator <(const P &a,const P &b){//按f(n)=g(n)+h(n)大小排序
return a.d+a.w>b.d+b.w; //最大堆
}
}p;
const int N=3;//棋盘大小
const string t="123405678";//目标状态
相关文档
最新文档