八数码问题C语言A星算法详细实验报告含代码文档格式.docx
- 文档编号:17407580
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:13
- 大小:230.35KB
八数码问题C语言A星算法详细实验报告含代码文档格式.docx
《八数码问题C语言A星算法详细实验报告含代码文档格式.docx》由会员分享,可在线阅读,更多相关《八数码问题C语言A星算法详细实验报告含代码文档格式.docx(13页珍藏版)》请在冰豆网上搜索。
(n)是n到目标的最短路经的启发值。
由于这个f'
(n)其实是无法预先知道的,所以实际上使用的是下面的估价函数:
f(n)=g(n)+h(n)
其中g(n)是从初始结点到节点n的实际代价,h(n)是从结点n到目标结点的最佳路径的估计代价。
在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。
用f(n)作为f'
(n)的近似,也就是用g(n)代替g'
(n),h(n)代替h'
(n)。
这样必须满足两个条件:
(1)g(n)>
=g'
(n)(大多数情况下都是满足的,可以不用考虑),且f必须保持单调递增。
(2)h必须小于等于实际的从当前节点到达目标节点的最小耗费h(n)<
=h'
第二点特别的重要。
可以证明应用这样的估价函数是可以找到最短路径的。
3.A*算法的步骤
A*算法基本上与广度优先算法相同,但是在扩展出一个结点后,要计算它的估价函数,并根据估价函数对待扩展的结点排序,从而保证每次扩展的结点都是估价函数最小的结点。
A*算法的步骤如下:
1)建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头和尾指针。
2)取出队列头(队列头指针所指)的结点,如果该结点是目标结点,则输出路径,程序结束。
否则对结点进行扩展。
3)检查扩展出的新结点是否与队列中的结点重复,若与不能再扩展的结点重复(位于队列头指针之前),则将它抛弃;
若新结点与待扩展的结点重复(位于队列头指针之后),则比较两个结点的估价函数中g的大小,保留较小g值的结点。
跳至第五步。
4)如果扩展出的新结点与队列中的结点不重复,则按照它的估价函数f大小将它插入队列中的头结点后待扩展结点的适当位置,使它们按从小到大的顺序排列,最后更新队列尾指针。
5)如果队列头的结点还可以扩展,直接返回第二步。
否则将队列头指针指向下一结点,再返回第二步。
四、程序框图
五、实验结果及分析
输入初始状态:
283目标状态:
123
164804
705765
运行结果屏幕打印
OPEN表与CLOSE表:
OPEN
CLOSE
1234
23456
01
23467
015
234689
0157
2348910
01576
2348111213
015769
234812131415
01576911
348121314151617
015769112
481213141516171819
0157691123
481213141516171920
015769112318
8121314151617192122
0157691123184
12131415161719212223
01576911231848
1213141516171921222425
0157691123184823
1213141516171921222426
015769112318482324
发现26为目标节点
0…7
283
104
765
搜索树:
六、结论
对于八数码问题,BFS算法最慢,A*算法较快。
八数码问题的一个状态实际上是0~9的一个排列,对于任意给定的初始状态和目标,不一定有解,也就是说从初始状态不一定能到达目标状态。
因为排列有奇排列和偶排列两类,从奇排列不能转化成偶排列。
如果一个数字0~8的随机排列871526340,用F(X)表示数字X前面比它小的数的个数,全部数字的F(X)之和为Y=∑(F(X)),如果Y为奇数则称原数字的排列是奇排列,如果Y为偶数则称原数字的排列是偶排列。
因此,可以在运行程序前检查初始状态和目标状态的排序的奇偶行是否相同,相同则问题可解,应当能搜索到路径。
否则无解。
七、源程序及注释
#include<
iostream>
ctime>
vector>
usingnamespacestd;
constintROW=3;
constintCOL=3;
constintMAXDISTANCE=10000;
constintMAXNUM=10000;
intabs(inta)
{
if(a>
0)returna;
elsereturn-a;
}
typedefstruct_Node{
intdigit[ROW][COL];
intdist;
//距离
intdep;
//深度
intindex;
//索引值
}Node;
Nodesrc,dest;
vector<
Node>
node_v;
//储存节点
boolisEmptyOfOPEN(){//判断Open表是否空
for(inti=0;
i<
node_v.size();
i++){
if(node_v[i].dist!
=MAXNUM)
returnfalse;
returntrue;
boolisEqual(intindex,intdigit[][COL]){//判断节点是否与索引值指向的节点相同
ROW;
i++)
for(intj=0;
j<
COL;
j++){
if(node_v[index].digit[i][j]!
=digit[i][j])
}
ostream&
operator<
<
(ostream&
os,Node&
node){
j++)
os<
node.digit[i][j]<
'
;
endl;
returnos;
voidPrintSteps(intindex,vector<
&
rstep_v){//输出步骤
rstep_v.push_back(node_v[index]);
index=node_v[index].index;
while(index!
=0){
rstep_v.push_back(node_v[index]);
index=node_v[index].index;
for(inti=rstep_v.size()-1;
i>
=0;
i--)
cout<
"
Step"
<
rstep_v.size()-i
endl<
rstep_v[i]<
voidSwap(int&
a,int&
b){//交换
intt;
t=a;
a=b;
b=t;
voidAssign(Node&
node,intindex){//获取节点
node.digit[i][j]=node_v[index].digit[i][j];
intGetMinNode(){//获取启发值最小的节点
intdist=MAXNUM;
intloc;
//thelocationofminimizenode
if(node_v[i].dist==MAXNUM)
continue;
elseif((node_v[i].dist+node_v[i].dep)<
dist){
loc=i;
dist=node_v[i].dist+node_v[i].dep;
returnloc;
boolisExpandable(Node&
node){//判断是否可扩展
if(isEqual(i,node.digit))
intDistance(Node&
node,intdigit[][COL]){//计算距离
intdistance=0;
boolflag=false;
for(inti=0;
i++)
j++)
for(intk=0;
k<
k++){
for(intl=0;
l<
l++){
if(node.digit[i][j]==digit[k][l]){
distance+=abs(i-k)+abs(j-l);
flag=true;
break;
else
flag=false;
if(flag)
returndistance;
intMinDistance(inta,intb){//二者取小
return(a<
b?
a:
b);
voidProcessNode(intindex){//展开节点
intx,y;
boolflag;
if(node_v[index].digit[i][j]==0){
x=i;
y=j;
elseflag=false;
if(flag)
Nodenode_up;
//上移操作
Assign(node_up,index);
intdist_up=MAXDISTANCE;
if(x>
0){
Swap(node_up.digit[x][y],node_up.digit[x-1][y]);
if(isExpandable(node_up)){
dist_up=Distance(node_up,dest.digit);
node_up.index=index;
node_up.dist=dist_up;
node_up.dep=node_v[index].dep+1;
node_v.push_back(node_up);
Nodenode_down;
//下移操作
Assign(node_down,index);
intdist_down=MAXDISTANCE;
if(x<
2){
Swap(node_down.digit[x][y],node_down.digit[x+1][y]);
if(isExpandable(node_down)){
dist_down=Distance(node_down,dest.digit);
node_down.index=index;
node_down.dist=dist_down;
node_down.dep=node_v[index].dep+1;
node_v.push_back(node_down);
Nodenode_left;
//左移操作
Assign(node_left,index);
intdist_left=MAXDISTANCE;
if(y>
Swap(node_left.digit[x][y],node_left.digit[x][y-1]);
if(isExpandable(node_left)){
dist_left=Distance(node_left,dest.digit);
node_left.index=index;
node_left.dist=dist_left;
node_left.dep=node_v[index].dep+1;
node_v.push_back(node_left);
Nodenode_right;
//右移操作
Assign(node_right,index);
intdist_right=MAXDISTANCE;
if(y<
Swap(node_right.digit[x][y],node_right.digit[x][y+1]);
if(isExpandable(node_right)){
dist_right=Distance(node_right,dest.digit);
node_right.index=index;
node_right.dist=dist_right;
node_right.dep=node_v[index].dep+1;
node_v.push_back(node_right);
node_v[index].dist=MAXNUM;
intmain(){
intnumber;
cout<
输入初始状态:
"
cin>
>
number;
src.digit[i][j]=number;
src.index=0;
src.dep=1;
输入目标状态"
for(intm=0;
m<
m++)
for(intn=0;
n<
n++){
dest.digit[m][n]=number;
node_v.push_back(src);
while
(1){
if(isEmptyOfOPEN()){
找不到解!
return-1;
else{
intloc;
//thelocationoftheminimizenode
loc=GetMinNode();
if(isEqual(loc,dest.digit)){
vector<
rstep_v;
初始状态:
src<
PrintSteps(loc,rstep_v);
成功!
ProcessNode(loc);
return0;
如有侵权请联系告知删除,感谢你们的配合!
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数码 问题 语言 算法 详细 实验 报告 代码