A星算法求解八数码技术报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

A*算法求解八数码问题
●open 表、closed 表数据结构的选择:
1)把s放入open表,记f=h,令closed为空表。

2)重复下列过程,直到找到目标节点为止。

若open表为空表,则宣告失败。

3)选取open表中未设置过的具有最小f值的节点为最佳节点bestnode,并把它放入
closed表。

4)若bestnode为一目标节点,则成功求得一解。

5)若bestnode不是目标节点,则扩展之,产生后继节点succssor。

6)对每个succssor进行下列过称:
a)对每个succssor返回bestnode的指针。

b)计算g(suc)=g(bes)+k(bes,suc)。

c)如果succssore open,称此节点为old,并填到bestnode的后继节点表中。

d)比较新旧路劲代价。

如果g(suc)<g(old),则重新确定old的父辈节点为
bestnode,记下较小代价g(old),并修真f(old)值。

e)若至old节点的代价较低或一样,则停止扩展节点。

f)若succssore不再closed表中,则看其是否在closed表中。

g)若succssore在closed表中,则转向(c)。

h)若succssore既不在open表中,又不在closed表中,则把它放入open表中,
并添入bestnode后裔表中,然后转向(7)。

i)计算f值
j)Go loop
●节点的数据结构:
static int target[9]={1,2,3,8,0,4,7,6,5}; 全局静态变量,表示目标状态
class eight_num
{
private:
int num[9]; 定义八数码的初始状态
int not_in_position_num; 定义不在正确位置八数码的个数
int deapth; 定义了搜索的深度
int eva_function; 评价函数的值,每次选取最小的进行扩展
public:
eight_num* parent; 指向节点的父节点
eight_num* leaf_next; 指向open表的下一个节点
eight_num* leaf_pre; 指向open 表的前一个节点
初始状态的构造函数
eight_num(int init_num[9]);
eight_num(int num1,int num2,int num3,int num4,int num5,int num6,int num7,int num8,int num9){}
eight_num(void){ }
计算启发函数g(n)的值
void eight_num::cul_para(void){}
显示当前节点的状态
void eight_num::show(){}
复制当前节点状态到一个另数组中
void eight_num::get_numbers_to(int other_num[9]){}
设置当前节点状态(欲设置的状态记录的other数组中)
void eight_num::set_num(int other_num[9]){}
eight_num& eight_num::operator=(eight_num& another_8num){} eight_num& eight_num::operator=(int other_num[9]){}
int eight_num::operator==(eight_num& another_8num){}
int eight_num::operator==(int other_num[9]){}
空格向上移
int move_up(int num[9]){}
空格向下移
int move_down(int num[9]){}
空格向左移
int move_left(int num[9]){}
空格向右移
int move_right(int num[9]){}
判断可否解出
int icansolve(int num[9],int target[9]){}
判断有无重复
int existed(int num[9],eight_num *where){}
寻找估价函数最小的叶子节点
eight_num* find_OK_leaf(eight_num* start){}
}
A*算法求解框图:
●分析估价函数对搜索算法的影响:
估价函数就是评价函数,它用来评价子结点的好坏,因为准确评价是不可能的,所以称为估值。

这就是我们所谓的有信息搜索。

如果估值函数只考虑结点的某种性能上的价值,而不考虑深度,比较有名的就是有序搜索(Ordered-Search),它着重看好能否找出解,而不看解离起始结点的距离(深度)。

如果估值函数考虑了深度,或者是带权距离(从起始结点到目标结点的距离加权和),那就是A*如果不考虑深度,就是说不要求最少步数,移动一步就相当于向后多展开一层结点,深度多算一层,如果要求最少步数,那就需要用A*。

简单的来说A*就是将估值函数分成两个部分,一个部分是路径价值,另一个部分是一般性启发价值,合在一起算估整个结点的价值,考虑到八数码问题的特点,在本实验中使用A*算法求解。

●分析A*算法的特点:
A*搜索是一种效的搜索算法,它把到达节点的耗散g(n)和从该节点到目标节点的消耗h(n)结合起来对节点进行评价:f(n)=g(n)+h(n)。

当h(n)是可采纳时,使用Tree-Search 的A*算法将是最优的。

●实验结果:
附录:
源代码及其注释
#include "iostream.h"
#include <time.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
static int target[9]={1,2,3,8,0,4,7,6,5};
//class definition
class eight_num
{
private:
int num[9];
int not_in_position_num;
int deapth;
int eva_function;
public:
eight_num* parent;
eight_num* leaf_next;
eight_num* leaf_pre;
eight_num(int init_num[9]);
eight_num(int num1,int num2,int num3,int num4,int num5,int num6,int num7,int num8,int num9)
{
num[0]=num1;
num[1]=num2;
num[2]=num3;
num[3]=num4;
num[4]=num5;
num[5]=num6;
num[6]=num7;
num[7]=num8;
num[8]=num9;
}
eight_num(void)
{
for (int i=0;i<9;i++)
num[i]=i;
}
void cul_para(void);
void get_numbers_to(int other_num[9]);
int get_nipn(void)
{return not_in_position_num;}
int get_deapth(void)
{return deapth;}
int get_evafun(void)
{return eva_function;}
void set_num(int other_num[9]);
void show(void);
eight_num& operator=(eight_num&);
eight_num& operator=(int other_num[9]);
int operator==(eight_num&);
int operator==(int other_num[9]);
};
//计算启发函数g(n)的值
void eight_num::cul_para(void)
{
int i;
int temp_nipn=0;
for (i=0;i<9;i++)
if (num[i]!=target[i])
temp_nipn++;
not_in_position_num=temp_nipn;
if (this->parent==NULL)
deapth=0;
else
deapth=this->parent->deapth+1;
eva_function=not_in_position_num+deapth; }
//构造函数1
eight_num::eight_num(int init_num[9])
{
for (int i=0;i<9;i++)
num[i]=init_num[i];
}
//显示当前节点的状态
void eight_num::show()
{
cout<<num[0];
cout<<" ";
cout<<num[1];
cout<<" ";
cout<<num[2];
cout<<"\n";
cout<<num[3];
cout<<" ";
cout<<num[4];
cout<<" ";
cout<<num[5];
cout<<"\n";
cout<<num[6];
cout<<" ";
cout<<num[7];
cout<<" ";
cout<<num[8];
cout<<"\n";
}
//复制当前节点状态到一个另数组中
void eight_num::get_numbers_to(int other_num[9])
{
for (int i=0;i<9;i++)
other_num[i]=num[i];
}
//设置当前节点状态(欲设置的状态记录的other数组中) void eight_num::set_num(int other_num[9])
{
for (int i=0;i<9;i++)
num[i]=other_num[i];
}
eight_num& eight_num::operator=(eight_num& another_8num) {
for (int i=0;i<9;i++)
num[i]=another_8num.num[i];
not_in_position_num=another_8num.not_in_position_num;
deapth=another_8num.deapth+1;
eva_function=not_in_position_num+deapth;
return *this;
}
eight_num& eight_num::operator=(int other_num[9])
{
for (int i=0;i<9;i++)
num[i]=other_num[i];
return *this;
}
int eight_num::operator==(eight_num& another_8num) {
int match=1;
for (int i=0;i<9;i++)
if(num[i]!=another_8num.num[i])
{
match=0;
break;
}
if (match==0)
return 0;
else
return 1;
}
int eight_num::operator==(int other_num[9])
{
int match=1;
for (int i=0;i<9;i++)
if(num[i]!=other_num[i])
{
match=0;
break;
}
if (match==0)
return 0;
else
return 1;
}
//class definition over
//*************************
//空格向上移
int move_up(int num[9])
{
for (int i=0;i<9;i++)
if (num[i]==0)
break;
if (i<3)
return 0;
else
{
num[i]=num[i-3];
num[i-3]=0;
return 1;
}
}
//空格向下移
int move_down(int num[9]) {
for (int i=0;i<9;i++)
if (num[i]==0)
break;
if (i>5)
return 0;
else
{
num[i]=num[i+3];
num[i+3]=0;
return 1;
}
}
//空格向左移
int move_left(int num[9]) {
for (int i=0;i<9;i++)
if (num[i]==0)
break;
if (i==0||i==3||i==6)
return 0;
else
{
num[i]=num[i-1];
num[i-1]=0;
return 1;
}
}
//空格向右移
int move_right(int num[9]) {
for (int i=0;i<9;i++)
if (num[i]==0)
break;
if (i==2||i==5||i==8)
return 0;
else
{
num[i]=num[i+1];
num[i+1]=0;
return 1;
}
}
//判断可否解出
int icansolve(int num[9],int target[9])
{
int i,j;
int count_num,count_target;
for (i=0;i<9;i++)
for (j=0;j<i;j++)
{
if(num[j]<num[i]&&num[j]!=0)
count_num++;
if(target[j]<target[i]&&target[j]!=0)
count_target++;
}
if((count_num+count_target)%2 == 0)
return 1;
else
return 0;
}
//判断有无重复
int existed(int num[9],eight_num *where)
{
eight_num *p;
for(p=where;p!=NULL;p=p->parent)
if(*p==num)
return 1;
return 0;
}
//寻找估价函数最小的叶子节点
eight_num* find_OK_leaf(eight_num* start) {
eight_num *p,*OK;
p=OK=start;
int min=start->get_evafun();
for(p=start;p!=NULL;p=p->leaf_next)
if(min>p->get_evafun())
{
OK=p;
min=p->get_evafun();
}
return OK;
}
//主函数开始
int main(void)
{
double time;
clock_t Start,Finish;
int memery_used=0,step=0;
int num[9];
int flag=0;//是否输入错误标志,1表示输入错误
int bingo=0;//是否查找成功标志,1表示成功
int i,j;
cout<<"请输入数字0-8 (0表示空格):\n";
for (i=0;i<9;i++)
{
flag=0;
cin>>num[i];
for(j=0;j<i;j++)
if(num[i]==num[j])
flag=1;
if (num[i]<0||num[i]>8||flag==1)
{
i--;
cout<<"数字不合法!\t请重输!\n";
}
}
eight_num S(num),Target(target);
S.parent=S.leaf_next=S.leaf_pre=NULL;
S.cul_para();
memery_used++;
cout<<"起始数字组是:\n";
S.show();
cout<<"目标数字组是:\n";
Target.show();
if(!icansolve(num,target))
{
cout<<"无法解决!\n";
cin>>i;
return 1;
}
Start=clock( );
eight_num *OK_leaf=&S,*leaf_start=&S,*new_8num,*p;
while(OK_leaf!=NULL&&bingo!=1)
{
OK_leaf=find_OK_leaf(leaf_start);
if(*OK_leaf==Target)
{
bingo=1;
break;
}
p=OK_leaf->leaf_pre;
OK_leaf->get_numbers_to(num);
if(move_up(num)&&!existed(num,OK_leaf)) {
new_8num=new eight_num;
new_8num->set_num(num);
new_8num->parent=OK_leaf;
new_8num->cul_para();
new_8num->leaf_pre=p;
if(p==NULL)
leaf_start=new_8num;
else
p->leaf_next=new_8num;
p=new_8num;
memery_used++;
}
OK_leaf->get_numbers_to(num);
if(move_down(num)&&!existed(num,OK_leaf)) {
new_8num=new eight_num;
new_8num->set_num(num);
new_8num->parent=OK_leaf;
new_8num->cul_para();
new_8num->leaf_pre=p;
if(p==NULL)
leaf_start=new_8num;
else
p->leaf_next=new_8num;
p=new_8num;
memery_used++;
}
OK_leaf->get_numbers_to(num);
if(move_left(num)&&!existed(num,OK_leaf)) {
new_8num=new eight_num;
new_8num->set_num(num);
new_8num->parent=OK_leaf;
new_8num->cul_para();
new_8num->leaf_pre=p;
if(p==NULL)
leaf_start=new_8num;
else
p->leaf_next=new_8num;
p=new_8num;
memery_used++;
}
OK_leaf->get_numbers_to(num);
if(move_right(num)&&!existed(num,OK_leaf))
{
new_8num=new eight_num;
new_8num->set_num(num);
new_8num->parent=OK_leaf;
new_8num->cul_para();
new_8num->leaf_pre=p;
if(p==NULL)
leaf_start=new_8num;
else
p->leaf_next=new_8num;
p=new_8num;
memery_used++;
}
p->leaf_next=OK_leaf->leaf_next;
if(OK_leaf->leaf_next!=NULL)
OK_leaf->leaf_next->leaf_pre=p;
OK_leaf->leaf_next=OK_leaf->leaf_pre=NULL;
}
Finish=clock( );
if(bingo==1)
{
time = (double)(Finish-Start)*1000/CLOCKS_PER_SEC;
eight_num *p;
for (p=OK_leaf->parent;p!=NULL;p=p->parent)
{
cout<<" ^\n";
p->show();
step++;
}
cout<<"耗时:";
cout<<time;
cout<<"ms\n";
cout<<"步数:";
cout<<step;
cout<<"\n";
}
else
cout<<"查找失败!";
return 0;
}。

相关文档
最新文档