A星算法求解8数码问题实验Word下载.docx

上传人:b****5 文档编号:21260829 上传时间:2023-01-29 格式:DOCX 页数:18 大小:106.32KB
下载 相关 举报
A星算法求解8数码问题实验Word下载.docx_第1页
第1页 / 共18页
A星算法求解8数码问题实验Word下载.docx_第2页
第2页 / 共18页
A星算法求解8数码问题实验Word下载.docx_第3页
第3页 / 共18页
A星算法求解8数码问题实验Word下载.docx_第4页
第4页 / 共18页
A星算法求解8数码问题实验Word下载.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

A星算法求解8数码问题实验Word下载.docx

《A星算法求解8数码问题实验Word下载.docx》由会员分享,可在线阅读,更多相关《A星算法求解8数码问题实验Word下载.docx(18页珍藏版)》请在冰豆网上搜索。

A星算法求解8数码问题实验Word下载.docx

4、A*算法总结

4、1,把起始状态添加到开启列表。

4、2,重复如下工作:

  a) 寻找开启列表中f值最低的节点,我们称它为BESTNOE

  b)把它切换到关闭列表中。

c) 对相邻的4个节点中的每一个

   *假如它不在开启列表,也不在关闭列表,把它添加到开启列表中。

把BESTNODE作为这一节点的父节点。

记录这一节点的f与g值

   *假如它已在开启或关闭列表中,用g值为参考检查新的路径是否更好。

更低的g值意味着更好的路径、假如如此,就把这一节点的父节点改为BESTNODE,同时重新计算这一节点的f与g值,假如保持开启列表的f值排序,改变之后需要重新对开启列表排序。

d)停止

 把目标节点添加到关闭列表,这时候路径被找到,或者没有找到路径,开启列表差不多空了,这时候路径不存在、

 4、3,保存路径、从目标节点开始,沿着每一节点的父节点移动直到回到起始节点、这就是求得的路径。

5、数据结构

采纳结构体来保存八数码的状态、f与g的值以及该节点的父节点;

structNode{

int s[3][3];

//保存八数码状态,0代表空格

 intf,g;

//启发函数中的f与g值

structNode* next;

 structNode*previous;

//保存其父节点

};

6、实验结果,如图3所示

图3 A*算法求解八数码问题实验结果

7、源代码

//——--——-—-——-—--—-----———---———-—--—--—-————-—---—-———-——-----—-—-——-——---———-

//代码:

利用A*算法求解八数码问题、

//八数码问题的启发函数设计为:

f(n)=d(n)+p(n),其中A*算法中的g(n)依照具体情况设计为d(n),意为n节点的深度,而h(n)设计为p(n),意为放错的数码与正确的位置距离之与、

//后继结点的获取:

数码的移动等效为空格的移动。

首先判断空格上下左右的可移动性,其次移动空格获取后继结点。

//---————————--—-——---————-———---——--—-—-—-—--—-—--——---—----——--—-----———---——

#include〈stdio、h>

#include〈stdlib、h〉

#include〈math、h>

//八数码状态对应的节点结构体

struct Node{

ints[3][3];

//保存八数码状态,0代表空格

 intf,g;

//启发函数中的f与g值

structNode* next;

structNode*previous;

int open_N=0;

//记录Open列表中节点数目

//八数码初始状态

intinital_s[3][3]={

2,8,3,

1,6,4,

7,0,5

};

//八数码目标状态

int final_s[3][3]={

 1,2,3,

 8,0,4,

7,6,5

};

//-———----—--—————-——————————-————-——-————-—-———-----—-—---—————---———-——-

//添加节点函数入口,方法:

通过插入排序向指定表添加

//—-——--—--—--————-—---——-——---—----—-—---—---—-—-——-————--——-—-—---————--

void Add_Node(struct Node*head,struct Node*p)

{

 struct Node*q;

if(head—〉next)//考虑链表为空

{  q= head-〉next;

ﻩif(p-〉f <

head—>next->f){//考虑插入的节点值比链表的第一个节点值小

ﻩﻩﻩp—>next=head—〉next;

ﻩﻩhead->next= p;

ﻩ}

else{

ﻩ while(q-〉next)//考虑插入节点x,形如a<

=x<

=b

ﻩ {

ﻩif((q-〉f <

 p—〉f||q—〉f==p-〉f)&&

(q->

next—>

f >

 p->

f||q—〉next-〉f==p—>

f)){

ﻩﻩﻩ p-〉next=q—>

next;

ﻩﻩﻩ q-〉next=p;

ﻩ break;

ﻩﻩﻩ}

ﻩ q=q-〉next;

ﻩif(q-〉next==NULL)//考虑插入的节点值比链表最后一个元素的值更大

ﻩﻩq—>next = p;

ﻩ }

 }

 else head->next=p;

//——--—--—-—————-—-———--—--——-——--—---—-——---—-—-—--—-—-----——-----——--—-—

//删除节点函数入口

//——--—————--———————--—---—--————---—--——--——--—-—--——----——--——-——----——-

void del_Node(structNode*head,structNode *p )

structNode*q;

q=head;

while(q->next)

ﻩif(q—〉next==p){

ﻩ  q-〉next= p->next;

ﻩp-〉next=NULL;

ﻩ if(q->

next ==NULL)return;

   //free(p);

 }

q=q—〉next;

}

//--—-—--——-—--———------————-—-——-—-—-——--—————-——--—--——--—-—-—--———-—-—-

//判断两个数组是否相等函数入口

//-——-——————---———-———-——-—--—-—--———-——-—-———-—--—-——-——-—-—-——--—----—-—

intequal(ints1[3][3],ints2[3][3])

inti,j,flag=0;

 for(i=0;

i<

3;

i++)

ﻩfor(j=0;

j〈3 ;

j++)

ﻩﻩif(s1[i][j]!

=s2[i][j]){flag=1;

break;

if(!

flag)

ﻩreturn 1;

else return0;

//——-—-—------———--——-----———-———---———--—---—-----——-—-——--——-—-—----——-—

//判断后继节点是否存在于Open或Closed表中函数入口

//---—-—-—---—-—-——-—-———-———————-—-———--—-—-----—-—-——-—-—-——-————---—--—

intexit_Node(struct Node*head,ints[3][3],structNode*Old_Node)

 structNode*q=head-〉next;

intflag =0;

while(q)

ﻩ if(equal(q—>

s,s)){

ﻩﻩflag=1;

ﻩﻩOld_Node—>next=q;

ﻩ return 1;

ﻩ else q= q—>next;

if(!

flag)return0;

//——-------——----—-—--———----—--—-——-----—-------————---—-——-————------—--

//计算p(n)的函数入口

//其中p(n)为放错位的数码与其正确的位置之间距离之与

//具体方法:

放错位的数码与其正确的位置对应下标差的绝对值之与

//--———---——-——-—————--——--—-----——--——---———-——-——-—-—————-———-——--—----—

intwrong_sum(ints[3][3])

inti,j,fi,fj,sum=0;

for(i=0 ;

i<3;

 i++)

ﻩfor(j=0;

j〈3;

 j++)

ﻩfor(fi=0;

fi<

3;

 fi++)

ﻩ  for(fj=0;

fj〈3;

fj++)

ﻩﻩif((final_s[fi][fj]== s[i][j])){

   sum+=fabs(i—fi)+fabs(j—fj);

ﻩ break;

ﻩ  }

ﻩ 

ﻩ}

returnsum;

//-—-—-———-------————-—---—-—---—--—--—--————-—--—------—-—-----———-—-—--—

//获取后继结点函数入口

//检查空格每种移动的合法性,假如合法则移动空格得到后继结点

//———-—-—--—-——---—-—-—-—-———-———---———-—-—-——--———---—-——-—--—————------—

intget_successor(struct Node*BESTNODE,intdirection, structNode*Successor)//扩展BESTNODE,产生其后继结点SUCCESSOR

int i,j,i_0,j_0,temp;

 for(i=0;

 i〈3;

i++)

for(j=0;

 j〈3;

 j++)

ﻩSuccessor->

s[i][j]= BESTNODE—〉s[i][j];

//获取空格所在位置

 for(i=0;

i<

3;

for(j=0;

 j<

j++)

ﻩﻩif(BESTNODE->

s[i][j]== 0){i_0=i;

j_0=j;

break;

switch(direction)

 {

ﻩcase 0:

if((i_0-1)>—1){

ﻩtemp =Successor-〉s[i_0][j_0];

ﻩﻩﻩ Successor—〉s[i_0][j_0]= Successor->s[i_0-1][j_0];

ﻩﻩSuccessor->

s[i_0—1][j_0]=temp;

ﻩﻩreturn 1;

ﻩﻩ}

ﻩ elsereturn 0;

ﻩﻩﻩﻩ

ﻩcase 1:

 if((j_0-1)〉—1){

ﻩﻩ  temp =Successor->

s[i_0][j_0];

ﻩﻩ Successor->s[i_0][j_0]=Successor—>

s[i_0][j_0-1];

ﻩSuccessor—〉s[i_0][j_0—1]=temp;

ﻩﻩﻩ return1;

ﻩ}

ﻩ  else return0;

ﻩcase2:

if((j_0+1)<3){

ﻩﻩ temp=Successor—>s[i_0][j_0];

ﻩﻩSuccessor-〉s[i_0][j_0]=Successor-〉s[i_0][j_0+1];

ﻩﻩ Successor—〉s[i_0][j_0+1]= temp;

ﻩﻩﻩreturn1;

ﻩﻩ}

  elsereturn0;

ﻩﻩﻩ

ﻩ case3:

if((i_0+1)〈3){

ﻩﻩ temp =Successor—>

s[i_0][j_0];

ﻩﻩSuccessor->s[i_0][j_0] =Successor->

s[i_0+1][j_0];

ﻩﻩﻩSuccessor-〉s[i_0+1][j_0]= temp;

ﻩﻩ  return1;

ﻩﻩ }

ﻩﻩ else return 0;

ﻩﻩ

 }

//----—-----—---—---—-——--—----——---—-—-—--——-—---——--—-———-----—--——-—--—

//从OPen表获取最佳节点函数入口

//—---—---—-———----——-—————-—-——--———-——-——-————---———-——---———-—-—-——-—--

struct Node*get_BESTNODE(struct Node*Open)

return Open—>

next;

//-——-—--—-—-----—--——-—----—---——————--——--—---—-———------———--———--—--——

//输出最佳路径函数入口

//-—-—--—--——-—----——-———--———---------———-—--—————---——-—--——-—-—————----

voidprint_Path(struct Node*head)

structNode*q,*q1,*p;

int i,j,count=1;

p=(structNode*)malloc(sizeof(structNode));

//通过头插法变更节点输出次序

p—〉previous=NULL;

 q=head;

 while(q)

 q1=q—>

previous;

  q—〉previous= p-〉previous;

p-〉previous = q;

q =q1;

q=p-〉previous;

while(q)

if(q==p->

previous)printf(”八数码的初始状态:

\n”);

elseif(q—〉previous==NULL)printf(”八数码的目标状态:

\n”);

  elseprintf("八数码的中间态%d\n”,count++);

for(i=0;

for(j=0;

ﻩ{

ﻩprintf(”%4d",q->

s[i][j]);

ﻩﻩif(j== 2)printf(”\n”);

ﻩ }

printf("

f=%d, g=%d\n\n”,q-〉f,q->

g);

 q= q->previous;

}

//————--—---——-—-—-—--———----———------———-—--———-—----————--—--—-————-—--—

//A*子算法入口:

处理后继结点

//-—-—-------——-----—---—--—-—————————-—----—---——-——---—---—---———-——————

voidsub_A_algorithm(structNode *Open, structNode*BESTNODE,structNode* Closed,struct Node *Successor)

structNode* Old_Node= (structNode*)malloc(sizeof(structNode));

 Successor->

previous= BESTNODE;

//建立从successor返回BESTNODE的指针

 Successor—>g =BESTNODE->g+ 1;

//计算后继结点的g值

//检查后继结点是否已存在于Open与Closed表中,假如存在:

该节点记为old_Node,比较后继结点的g值与表中old_Node节点

//g值,前者小代表新的路径比老路径更好,将Old_Node的父节点改为BESTNODE,并修改其f,g值,后者小则什么也不做。

//即不存在Open也不存在Closed表则将其加入OPen表,并计算其f值

 if(exit_Node(Open, Successor-〉s, Old_Node) ){

ﻩ if(Successor-〉g 〈Old_Node-〉g){

  Old_Node-〉next-〉previous =BESTNODE;

//将Old_Node的父节点改为BESTNODE

ﻩ Old_Node->

next->g=Successor-〉g;

//修改g值

ﻩ Old_Node—>

next-〉f=Old_Node—〉g + wrong_sum(Old_Node->

s);

//修改f值

ﻩﻩ//排序~~~~~~~~~~~~~~~~~~

ﻩﻩdel_Node(Open,Old_Node);

ﻩﻩ Add_Node(Open,Old_Node);

ﻩ}

ﻩ 

  }

ﻩelse if( exit_Node(Closed,Successor—>

s, Old_Node)){

    if(Successor-〉g<Old_Node—〉g){

ﻩ  Old_Node—>next->

previous=BESTNODE;

ﻩﻩOld_Node-〉next-〉g= Successor—〉g;

ﻩ Old_Node—>

f =Old_Node->g +wrong_sum(Old_Node-〉s);

ﻩﻩ//排序~~~~~~~~~~~~~~~~~~

ﻩﻩ del_Node(Closed,Old_Node);

Add_Node(Closed,Old_Node);

 ﻩ} 

ﻩ }

ﻩﻩ  else{

ﻩﻩSuccessor—〉f=Successor->

g +wrong_sum(Successor—〉s);

ﻩﻩﻩ  Add_Node(Open, Successor);

 

ﻩﻩ open_N++;

ﻩﻩ}

//-——--———-—---—-—-—---———--—-—-———-—--————-—----—--———-—------——---—-————

//A*算法入口

//八数码问题的启发函数为:

f(n)=d(n)+p(n)

//其中A*算法中的g(n)依照具体情况设计为d(n),意为n节点的深度,而h(n)设计为p(n),

//意为放错的数码与正确的位置距离之与

//-——-—---——-—-—---—-——-—--———--—-—-—---——--——-———---—--—---—--——--——--—-—

void A_algorithm(structNode *Open, structNode*Closed)//A*算法

inti,j;

struct Node*BESTNODE, *inital,*Successor;

inital = (structNode*)malloc(sizeof(struct Node));

//初始化起始节点

for(i=0;

i<3;

ﻩ for(j=0;

j<

j++)

ﻩinital—〉s[i][j] = inital_s[i][j];

inital->f =wrong_sum(inital_s);

inital-〉g=0;

inital—〉previous= NULL;

 inital—〉next =NULL;

 Add_Node(Open,inital);

//把初始节点放入OPEN表

open_N++;

while(1)

ﻩif(open_N ==0){printf("

failure!

”);

 return;

else {

ﻩﻩ BESTNODE=get_BESTNODE(Open);

//从OPEN表获取f值最小的BESTNODE,将其从OPEN表删除并加入CLOSED表中

ﻩﻩdel_Node(Open, BESTNODE);

ﻩﻩopen_N—-;

ﻩ  ﻩ Add_Node(Closed,BESTNODE);

ﻩﻩ if(equal(BESTNODE-〉s,final_s)){//判断BESTNODE是否为目标节点

ﻩﻩﻩprintf("

success!

\n");

ﻩﻩﻩ print_Path(BESTNODE);

ﻩﻩﻩ return;

ﻩ//针对八数码问题,后继结点Successor

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 销售营销

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1