八数码难题
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{ char cls[4]="cls",input='1'; int flag=1,sum=1;
while(input>='1'&&input<='4') {
open.clear(); closed.clear(); sum=1; flag=1; select(); cin>>input;
if(input>='1'&&input<='4') {
}
Baidu Nhomakorabea
} 四、
} }
实验分析
实验界面为:
本实验采取表的排序,并利用广度优先搜索来查找路径,基本实现了实验要求,仍 有不完善之处,仍需继续改正。
return pos>=0&&pos<3*3; } int isdiff(int ch[])//判断输入数码是否合法 {
for(int i=0;i<3*3-1;i++) for(int j=i+1;j<3*3;j++) if(ch[i]==ch[j]||!isok(i)||!isok(j)) return 0;
return pos+1;
return -1;
break;
case 2:
if(isok(pos+3))
return pos+3;
return -1;
break;
case 3:
if(isok(pos-1)&&pos/3==(pos-1)/3)
return pos-1;
return -1;
break;
}
{
int sum=0;
for(int i=0;i<3*3;i++)
sum+=getnum(i);
return sum; } int findzero(int ch[]) {
for(int i=0;i<3*3;i++) if(ch[i]==0) return i;
return -1; } void showparent(node *root)//递归方式显示结果路径 {
八数码难题
一、 问题简介 八方块移动游戏要求从一个含 8 个数字(用 1-8 表示)的方块以及一个空格方块(用
0 表示)的 3x3 矩阵的起始状态开始,不断移动该空格方块以使其和相邻的方块互换,直至 达到所定义的目标状态。空格方块在中间位置时有上、下、左、右 4 个方向可移动,在四个 角落上有 2 个方向可移动,在其他位置上有 3 个方向可移动。例如,假设一个 3x3 矩阵的初 始状态为:
} int findnext(int pos,int step)//找到移动位置
{
if(step>=0&&step<4)
//四个方向移动
{
switch(step)
{
case 0:
if(isok(pos-3))
return pos-3;
return -1;
break;
case 1:
if(isok(pos+1)&&pos/3==(pos+1)/3)
if(root->pre!=-1) {
showparent(&arr[root->pre]); root->show();cout<<"--第"<<root->precost+1<<"步--"<<endl; } } void showchar(int ch[])//显示一个状态 { for(int i=0;i<3*3;i++) { cout<<ch[i]<<" ";
803 214 765 目标状态为: 123 804 765 二、 算法分析
1、问题表示: 问题表示的核心是如何存储搜索过程中得到的状态。本人是这样存储的:对每个状态用 一个 9 位数存储,例如: 把初始状态: 803 214 765 存储为一个 9 位数:803214765 2、问题分析 想法一:采用插入排序的方法,八数码问题好比是一列数,将各个行列的数字按大小 排列,在插入的时候考虑方向性和比较性,对每个数字节点设置前后左右四个属性,分别在 初始状态比较各自队列的大小,比如按照左前右后顺时针的方向依次比较和移动,设置哨兵, 循环比较,最后得到的序列也就是八数码问题迎刃而解了。 想法二: 采用 prolog 语言表示, Prolog(Programming in Logic 的缩写)是一种逻辑编程语言。它建立在逻辑学的理论 基础之上, 最初被运用于自然语言等研究领域。现在它已广泛的应用在人工智能的研究中, 它可以用来建造专家系统、自然语言理解、智能知识库等。 2、 解题算法: 广度搜索常用的优化方法: 哈希表法——记录队列中已有节点,用于判断是否需要扩展节点。 A*算法——构造估价函数。 双向广度优先搜索——从源节点、目标节点一起开始搜索。 三、 算法实现
return 0; } else {
for(int i=0;i<3*3;i++) ch[i]=thisnode->ch1[i];
for(i=0;i<4;i++)//从四个方位搜索 {
int pos1=findnext(thisnode->pos,i);//搜索的位置 if(pos1!=-1)//搜索的位置合法 { swap(ch[pos1],ch[thisnode->pos]);//移动数码
if(hn>0)//如果没有到达目标状态 {
arr[sums].nextcost=hn; arr[sums].precost=thisnode->precost+1;// 已 经 走 过 的 路
程
arr[sums].pos=findzero(ch);//空格的位置 for(int j=0;j<3*3;j++)//当前的状态
return 1; } void init(int ch[],int flag)//初始化数码,键盘输入 {
cout<<"请输入目标状态:("<<3*3<<"个)"<<endl; for( int j=0;j<3*3;j++) cin>>chdes[j]; while(!(isdiff(chdes))) { cout<<"初始化错误,数据不合理!"<<endl; cout<<"请输入目标状态:("<<3*3<<"个)"<<endl; for( j=0;j<3*3;j++) cin>>chdes[j]; } cout<<"请输入初始状态:("<<3*3<<"个)"<<endl; for(j=0;j<3*3;j++) cin>>ch[j]; while(!(isdiff(ch))) { cout<<"初始化错误,数据不合理!"<<endl; cout<<"请输入初始状态:("<<3*3<<"个)"<<endl; for(j=0;j<3*3;j++) cin>>ch[j]; } for(j=0;j<3*3;j++) chbak[j]=ch[j];
本程序用了广度优先搜索这种策略进行搜索,且其搜索深度限制在 1000 内,其代码 实现如下:
#include "stack1.h" #include<time.h> stack open,closed;//表的基本操作
void swap(int &a,int &b)//比较数字 {
int bak=a; a=b; b=bak; } int isok(int pos)//界限判断 {
int hn=getallnum(); if(hn==0) {
cout<<"a solution is :"<<endl; showchar(chbak); cout<<"--第 1 步--"<<endl; showparent(thisnode); showchar(chdes);
return 1; } else
switch(input) {
case '1': init(ch,0); break;
case '2': system(cls); flag=2;
} if(flag==1) {
for(int i=0;i<maxsize;i++) arr[i].id=i;
arr[0].precost=0;arr[0].pre=-1;arr[0].pos=findzero(ch);arr[0].nextcost=getallnum(); for(i=0;i<3*3;i++) arr[0].ch1[i]=ch[i]; open.insert(&arr[0]); node *p=open.del(); closed.insert1(p); cout<<"目标状态:"<<endl; showchar(chdes); cout<<"初始状态:"<<endl; showchar(chbak); if(arr[0].nextcost>0) getpath(&arr[0],sum); else cout<<"初始状态为目标状态!"<<endl;
if((i+1)%3==0) cout<<endl;
} } int getpath(node *thisnode,int &sums)//递归方式搜索最优路径 {
if(sums>=9*maxsize/10) {
cout<<"应该是没有解路径,需要太多空间!(需存储 "<<jiecheng(3*3)<<" 个 状 态!)"<<endl;
}
return -1;
}
int getnum(int pos)
{
if(isok(pos))
{
for(int i=0;i<3*3;i++)
if(chdes[i]==ch[pos])
return(abs(i/3-pos/3)+abs(i%3-pos%3));
}
return 0;
}
int getallnum()
arr[sums].ch1[j]=ch[j]; arr[sums].pre=thisnode->id;
if(!(open.cmp(&arr[sums])||closed.cmp(&arr[sums]))) {
open.insert(&arr[sums]); sums++;
} } swap(ch[pos1],ch[thisnode->pos]); } } if(!open.isempty()) { node *tem=open.del(); closed.insert1(tem); getpath(tem,sums); } else { cout<<"没有解路径!"<<endl; return 0; } } return 0; } void main()