西电人工智能大作业
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
人工智能大作业
学生:021151**
021151**
时间:2013年12月4号
一.启发式搜索解决八数码问题
1. 实验目的
问题描述:现有一个3*3的棋盘,其中有0-8一共9个数字,0表示空格,其他的数字可以和0交换位置(只能上下左右移动)。给定一个初始状态和一个目标状态,找出从初始状态到目标状态的最短路径的问题就称为八数码问题。
例如:实验问题为
从初始状态:
要求编程解决这个问题,给出解决这个问题的搜索树以及从初始节点到目标
到目标状态:
节点的最短路径。
2.实验设备及软件环境
利用计算机编程软件Visual C++ 6.0,用C语言编程解决该问题。
3.实验方法
(1).算法描述:
①.把初始节点S放到OPEN表中,计算()
f S,并把其值与节点S联系起
来。
②.如果OPEN表是个空表,则失败退出,无解。
③.从OPEN表中选择一个f值最小的节点。结果有几个节点合格,当其
中有一个为目标节点时,则选择此目标节点,否则就选择其中任一节点作为节点i。
④.把节点i从OPEN表中移出,并把它放入CLOSED的扩展节点表中。
⑤.如果i是目标节点,则成功退出,求得一个解。
⑥.扩展节点i,生成其全部后继节点。对于i的每一个后继节点j:
a.计算()
f j。
b.如果j既不在OPEN表中,也不在CLOSED表中,则用估价函数f把
它添加入OPEN表。从j加一指向其父辈节点i的指针,以便一旦找
到目标节点时记住一个解答路径。
c.如果j已在OPEN表或CLOSED表上,则比较刚刚对j计算过的f值
和前面计算过的该节点在表中的f值。如果新的f值较小,则
I.以此新值取代旧值。
II.从j指向i,而不是指向它的父辈节点。
III.如果节点j在CLOSED表中,则把它移回OPEN表。
⑦转向②,即GO TO ②。
(2).流程图描述:
(3).程序源代码:
#include
#include
struct node{
int number[3][3];//用二维数组存放8数码
int W;//W表示与目标状态相比错放的数码数
int Depth;//记录当前节点的深度
struct node *parent;//指向父节点的指针
struct node *next;//指向链表中下一个节点的指针};
int CounterW(int Number[3][3])
{//函数说明:计算当前状态与目标状态的W值int i,j;
int W=0;
int Desnode[3][3]={1,2,3,8,0,4,7,6,5};
for(i=0; i<3; i++)
for(j=0; j<3; j++)
if(Number[i][j] != Desnode[i][j])
W++;
return W;
}
void PrintNode(node *A)
{
int i,j;
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
printf("%d ",A->number[i][j]);
printf("\n");
}
printf("\n");
}
int CheckNode(node *open, node *close, int a[3][3]) {//检验该节点状态是否出现过的子程序
int CheckFlag=0;
int flag1,flag2;
node *p=open;
node *q=close;
while(p != NULL)
{
flag1=0;
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
if(a[i][j]==p->number[i][j])
flag1++;
}
if(flag1 == 9)
break;
else
p=p->next;
}
while(q != NULL)
{
flag2=0;
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
if(a[i][j] == q->number[i][j])
flag2++;
}
if(flag2 == 9)
break;
else
q=q->next;
}
if((flag1==9) || (flag2==9))
CheckFlag=1;//如果出现过,置标志位为1
return CheckFlag;
}
struct node *FindNextNode(node *Prenode, node *open, node *close)
{ //扩展Prenode指向的节点,并将扩展所得结点组成一条单链表int i,j,m,n; //循环变量
int temp; //临时替换变量
int flag=0;
int a[3][3];//临时存放二维数组
struct node *p, *q, *head;
head=(node *)malloc(sizeof(node));//head指向该链表首结点,并且作为返回值
p=head;
q=head;
head->next=NULL;//初始化
for(i=0;i<3;i++)//找到二维数组中0的位置