八数码问题matlab实现,A* 算法解决八数码问题 matlab
1、问题描述
1.1什么是八数码问题
八数码游戏包括一个33的棋盘,棋盘上摆放着8个数字的棋子,留下一个空位。与空位相邻的棋子能够滑动到空位中。游戏的目的是要达到一个特定的目标状态。标注的形式化以下: 初始状态 7 5 3java
1 6 4c++
2 8 0算法
目标状态 1 2 3编程
8 0 4bash
7 6 5函数
1.2 问题的搜索形式描述
状态: 状态描述了8个棋子和空位在棋盘的9个方格上的分布。布局
初始状态: 任何状态均可以被指定为初始状态。学习
操做符: 用来产生4个行动(上下左右移动)。测试
目标测试: 用来检测状态是否能匹配上图的目标布局。优化
路径费用函数:每一步的费用为1,所以整个路径的费用是路径中的步数。
如今任意给定一个初始状态,要求找到一种搜索策略,用尽量少的步数获得上图的目标状态
1.3 算法思想
1.3.1 启发式搜索算法 有序搜索算法(A算法)
启发式搜索算法 A,通常简称 A算法 是一种典型的启发式搜索算法,其基本思想:
定义一个评估函数f,对当前的搜索状态进行评估,找到一个最有但愿的节点进行扩展。
评估函数的形式以下:
f(n)=g(n)+h(n)
其中:
n是被评估的节点
f(n) 是节点n从初始点到目标点的估价函数。
g(n) 是在状态空间中从初始节点到n节点的实际代价。
h(n)是从n到目标节点最佳路径的估计代价。
f(n)=g(n)+h(n) 表示从初始节点s通过节点n到目标节点g的评估代价
保证找到最短路径(最优解)的条件,关键在于估价函数h(n)的选取。估价值h(n)<= n到目标节点的距离实际值,这种状况下,搜索的点数多,搜索范围大,效率低。但能获得最优解。若是估价值>实际值, 搜索的点数少,搜索范围小,效率高,但不能保证获得最优解。
搜索中利用启发式信息,对当前未扩展结点根据设定的估价函数值选取离目标最近的结点进行扩展,从而缩小搜索空间,更快的获得最优解,提升效率。
1.3.1.1 A算法应用
在启发式搜索算法中,根据估价函数值,按由小到大的次序对Open表中的节点进行从新排序,这就是有序搜索法。所以,此时的Open表是一个按节点的启发估价函数值的大小为序排列的一个优先队。
有序搜索算法以下:
一、将初始节点S0放入Open表中;
二、如Open表为空,则搜索失败,退出;
三、把Open表的第一个节点取出,放入到Closed表中,并把该节点记为节点n;
四、若是节点n是目标节点,则搜索成功,求得一个解,退出;
五、扩展节点n,生成一组子节点,对既不在Open表中也不在Closed表中的子节点,计算出相应的估价函数值;
六、把节点n的子节点放到Open表中;
七、对Open表中的各节点按估价函数值从小到大排列;
八、转到2 。
1.3.2启发式搜索算法 A*算法
在A*算法中,启发性信息用一个特别的估价函数f*来表示:
f*(n)=g*(n)+h*(n)
式中:
g*(n)为从初始节点到节点n的最佳路径所付出的代价;
h*(n)是从n到目标节点的最佳路径所付出的代价;
f*(n)是从初始节点出发经过节点n到达目标节点的最佳路径的总代价。
(在这里要特别说明前面所说的f(n)=g(n)+h(n) 未带 * 为评估代价而非必定是最优代价)
基于上述g*(n)和h*(n)的定义,对启发式搜索算法中的g(n)和h(n)作以下限制:
①g(n)是对g*(n)的估计,且g(n)>0;
②h(n)是h*(n)的下界,即对任意节点n均有h(n)≤h*(n)。
在知足上述条件状况下的有序搜索算法称为A*算法。
对于某一搜索算法,当最佳路径存在时,就必定能找到它,则称此算法是可纳的。能够证实,A*算法是可纳算法。也就是说,对于有序搜索算法,当知足h(n)≤h*(n)条件时,只要最佳路径存在,就必定能找出这条路径。
2、问题解析
2.1 A*算法评估函数的分析
A* 算法的优劣性主要是靠评估函数的启发能力上,对于八数码问题
f*(n)=g*(n)+h*(n)
g*(n)是能够肯定的,对于h*(n)启发函数根据任意结点与目标之间的差别定义,例如取h(n)=w(n),咱们很容易知道,尽管对具体的h*(n)是多少咱们不知道,但根据“不在位”将牌个数这个估计,就能得出至少要移动多少步才能到达目标。若是启动函数根据考虑到任意结点与目标之间的距离的信息,例如取h(n)=P(n),P(n)定义为每个将牌与其目标位置之间的距离总和
例如:
任意状态s 7 5 3
1 6 4
2 8 0
目标状态g 1 2 3
8 0 4
7 6 5
中任意状态s中将牌 7 (1,1) 与目标状态 7 (3,1)距离为 L=|3-1|+|1-1|=2
P(n)=每个将牌与其目标位置之间的距离总和,
此外,咱们还发现
1 2 3 1 2 3
8 0 4 4 0 8
7 6 5 7 6 5
h(n)=P(n)不能估计出相邻两个将牌位置难易程度的影响,为此咱们再引入S(n)份量。S(n)是对结点n中将牌排列顺序的计分值,规定对非中心将牌,顺某一方向检查,若某一将牌后继将牌和目标状态所对应顺序不一致,这该将牌分值为2,一致为0;对于中心位置有将牌智估分值为1,无将牌(值为0时)估分值为0;对于非中心位置,每个将牌估分值总和加上中心位置估分值定义为S(n)。
依据这些启发信息,取:
h(n)=P(n)+3*S(n)
2.2八数码问题解决思路
2.2.1创建open表close表
根据须要open表和close表记录结点信息。OPEN表保存全部已生成而未考察的节点,CLOSED表中记录已访问过的节点。同时open表和close表里面所包含的结点状态不重复。每个结点需包含如下属性:
Struck{
父结点 数据(应为open表和close表数据惟一性可根据父节点信息找到父结点)prev
自己数据 con
总访问次数num
初始结点到该节点最小代价g(n)
按顺序 每个将牌估分值总和加上中心位置估分值s(n)
最终估计函数所得值也就是到达目标估计代价f(n)=g(n)+h(n)=g(n)+ P(n)+3*S(n)
}
2.2.2问题算法思路图形展现
总体思路就是根据代价最小进行扩展结点直到找到目标 代价计算钱,前面已经给出了说明。
f(n)=g(n)+h(n)=g(n)+ P(n)+3*S(n)
将要扩展的结点添加到close 进行扩展结点 将扩展结点添加到open里面,同时后从将该扩展结点代价值设置为无穷大(inf)
继续进行扩展结点 选择代价为最小的进行扩展将要扩展的结点添加到close 进行扩展结点 将扩展结点添加到open里面,同时后从将该扩展结点代价值设置为无穷大(inf)
继续扩展代价最小的结点
将要扩展的结点添加到close 进行扩展结点 将扩展结点添加到open里面,同时后从将该扩展结点代价值设置为无穷大(inf)
如此循环扩展open表里面最小代价结点直到找到目标
2.2.3 程序设计思路
我使用的是matlab 进行编程这是考虑matlab具备强大的功能,相对于c++、C 、java等其余语言它不须要定义任何变量,语言也是很是简单的
初始化
dis=[1 2 3;8 0 4;7 6 5];目标节点
//初始结点
f.prev=zeros(3);
f.con=[7 5 3;1 6 4;2 8 0];
f.num=1;
f.g=0;
f.s=gufei(f,dis);
f.fuc=valuefuc(f,dis);
y=dis;
将f结点添加到open表中
Open(1)=f
While{
for 找到open表中代价最小的节点 open(j)
将open(j)赋值给k
将k添加到close中
将open(j)从open中进行删除。
对结点k(代价最小结点)进行扩展结点
{
根据结点自己数据信息可获得相应的扩展结点
例如:
根据0 位于(3,3)可向上移或者右移
如获得
初始化该节点相关数据
将该节点加入到open表中
遍历open表删除相同结点(及查询刚刚添加的结点是否已经存在,存在则删除)
}
If close表里面时候存在目标结点
根据close表输出最短路径
}
3、 程序代码:
function []=bashuma
global e; %open表计数
global i; %close表计数
global m; %循环次数计数
a=0;b=0;n=0;i=0;
e=1;m=0;
%%
% *BOLD TEXT*
%初始化
dis=[1 2 3;8 0 4;7 6 5]; %目标节点
f.prev=zeros(3);
f.con=[7 5 3;1 6 4;2 8 0]; %初始节点
f.num=1;
f.g=0;
f.s=gufei(f,dis);
f.fuc=valuefuc(f,dis);
y=dis;
open(1)=f; %初始化Open表
k=f;
while a==0
m=m+1;
%设置循环次数
if m>=10000
disp('error!!');
break;
end
% 寻找代价最小值
for j=1:e
if k.fuc>open(j).fuc
k=open(j);
end
end
%%添CLOSE表
i=i+1;
j=k.num;
close(i)=k;
close(i).num=i;
%%删OPEN表
open(j).con=zeros(3);
open(j).fuc=inf;
%%是否找到目的节点
a=getit(close,dis);
if a==1
disp('success!!');
break;
end
%%扩展节点
open=opera(open,close,k,dis);
k.fuc=inf;
end
%输出路径
while 1
for j=1:i
if y==zeros(3)
b=1;
break;
end
if close(j).con==y
t=close(j).num;
n=n+1;
show(n)=t;
y=close(j).prev;
end
end
if b==1
break;
end
end
for j=1:n
close(show(n+1-j)).con
end
end
%查询是否找到目标节点
function a=getit(close,dis)
global i;
for j=1:i
if close(j).con==dis
a=1;
break;
else
a=0;
end
end
end
function ss= gufei( f,dis )
%UNTITLED5 Summary of this function goes here
% Detailed explanation goes here
s=0;
if f.con(2,2)~=0
s=s+1;
end
j=f.con(1,1);
if j~=0
if j==8
if f.con(1,2)~=1
s=s+2;
end
end
if j~=8
if f.con(1,2)~=j+1
s=s+2;
end
end
end
j=f.con(1,2);
if j~=0
if j==8
if f.con(1,3)~=1
s=s+2;
end
end
if j~=8
if f.con(1,3)~=j+1
s=s+2;
end
end
end
j=f.con(1,3);
if j~=0
if j==8
if f.con(2,3)~=1
s=s+2;
end
end
if j~=8
if f.con(2,3)~=j+1
s=s+2;
end
end
end
j=f.con(2,3);
if j~=0
if j==8
if f.con(3,3)~=1
s=s+2;
end
end
if j~=8
if f.con(3,3)~=j+1
s=s+2;
end
end
end
j=f.con(3,3);
if j~=0
if j==8
if f.con(3,2)~=1
s=s+2;
end
end
if j~=8
if f.con(3,2)~=j+1
s=s+2;
end
end
end
j=f.con(3,2);
if j~=0
if j==8
if f.con(3,1)~=1
s=s+2;
end
end
if j~=8
if f.con(3,1)~=j+1
s=s+2;
end
end
end
j=f.con(3,1);
if j~=0
if j==8
if f.con(2,1)~=1
s=s+2;
end
end
if j~=8
if f.con(2,1)~=j+1
s=s+2;
end
end
end
j=f.con(2,1);
if j~=0
if j==8
if f.con(1,1)~=1
s=s+2;
end
end
if j~=8
if f.con(1,1)~=j+1
s=s+2;
end
end
end
ss=s;
end
%上下左右移动操做
function open=opera(op,cl,f,dis)
global i;
[x,y]=find(f.con==0);
if x==1&&y==1
open=rt(f,op,cl,dis);
open=dn(f,open,cl,dis);
elseif x==1&&y==2
open=lt(f,op,cl,dis);
open=rt(f,open,cl,dis);
open=dn(f,open,cl,dis);
elseif x==1&&y==3
open=lt(f,op,cl,dis);
open=dn(f,open,cl,dis);
elseif x==2&&y==1
open=up(f,op,cl,dis);
open=rt(f,open,cl,dis);
open=dn(f,open,cl,dis);
elseif x==2&&y==2
open=lt(f,op,cl,dis);
open=up(f,open,cl,dis);
open=rt(f,open,cl,dis);
open=dn(f,open,cl,dis);
elseif x==2&&y==3
open=lt(f,op,cl,dis);
open=up(f,open,cl,dis);
open=dn(f,open,cl,dis);
elseif x==3&&y==1
open=up(f,op,cl,dis);
open=rt(f,open,cl,dis);
elseif x==3&&y==2
open=lt(f,op,cl,dis);
open=up(f,open,cl,dis);
open=rt(f,open,cl,dis);
elseif x==3&&y==3
open=lt(f,op,cl,dis);
open=up(f,open,cl,dis);
end
end
function open=rt(f,op,cl,dis)
global e;
e=e+1;
s=f;
[x,y]=find(s.con==0);
t=s.con(x,y+1);
s.con(x,y+1)=0;
s.con(x,y)=t;
s.num=e;
op(e).con=s.con;
op(e).prev=f.con;
op(e).num=e;
op(e).fuc=valuefuc(s,dis);
op(e).g=f.g+1;
op(e).s=gufei(s,dis);
search(s,op,cl);
open=op;
end
function open=up(f,op,cl,dis)
global e;
e=e+1;
s=f;
[x,y]=find(s.con==0);
t=s.con(x-1,y);
s.con(x-1,y)=0;
s.con(x,y)=t;
s.num=e;
op(e).con=s.con;
op(e).prev=f.con;
op(e).num=e;
op(e).fuc=valuefuc(s,dis);
op(e).g=f.g+1;
op(e).s=gufei(s,dis);
search(s,op,cl);
open=op;
end
function open=lt(f,op,cl,dis)
global e;
e=e+1;
s=f;
[x,y]=find(s.con==0);
t=s.con(x,y-1);
s.con(x,y-1)=0;
s.con(x,y)=t;
s.num=e;
op(e).con=s.con;
op(e).prev=f.con;
op(e).num=e;
op(e).fuc=valuefuc(s,dis);
op(e).g=f.g+1;
op(e).s=gufei(s,dis);
search(s,op,cl);
open=op;
end
function open=dn(f,op,cl,dis)
global e;
e=e+1;
s=f;
[x,y]=find(s.con==0);
t=s.con(x+1,y);
s.con(x+1,y)=0;
s.con(x,y)=t;
s.num=e;
op(e).con=s.con;
op(e).prev=f.con;
op(e).num=e;
op(e).fuc=valuefuc(s,dis);
op(e).g=f.g+1;
op(e).s=gufei(s,dis);
search(s,op,cl);
open=op;
end
function fuc=valuefuc(f,dis)
f.s=gufei(f,dis);
s1=f.g+3*f.s;
[x,y]=find(f.con==1);
s1=s1+abs(x-1)+abs(y-1);
[x,y]=find(f.con==2);
s1=s1+abs(x-1)+abs(y-2);
[x,y]=find(f.con==3);
s1=s1+abs(x-1)+abs(y-3);
[x,y]=find(f.con==4);
s1=s1+abs(x-2)+abs(y-3);
[x,y]=find(f.con==5);
s1=s1+abs(x-3)+abs(y-3);
[x,y]=find(f.con==6);
s1=s1+abs(x-3)+abs(y-2);
[x,y]=find(f.con==7);
s1=s1+abs(x-3)+abs(y-1);
[x,y]=find(f.con==8);
s1=s1+abs(x-2)+abs(y-1);
fuc=s1;
end
% 查询重复操做
function []=search(f,op,cl)
global e;
global i;
%e
%open(e-1).con
for j=1:e-1
if op(j).con==f.con
e=e-1;
break
end
end
for j=1:i-1
if cl(j).con==f.con
e=e-1;
break;
end
end
end
4、运行结果:
->
->
->
5、学习心得:
这个算法本身慢慢看书,从刚开始接触这究竟是什么鬼呀,到原来如此,最后到算法优化,总体感受仍是挺不错的。这个算法值得注意和思考的问题就是评估函数,评估函数直接影响到你的A*算法的效率,刚开始我选取的h(n)为p(n)------(每个将牌与其目标位置之间的距离总和)运行时间较为慢须要6秒左右,后面加上S(n) ------ (每个将牌估分值总和加上中心位置估分值)耗时只要1.5秒。
这是时隔很久才开始在csdn上发表博客了,之后继续要加油啊。
参考博客
http://blog.csdn.net/damotiansheng/article/details/40017107
八数码问题matlab实现,A* 算法解决八数码问题 matlab相关推荐
- 蚂蚁算法求解tsp问题matlab,蚁群算法解决TSP问题的MATLAB程序
蚁群算法TSP(旅行商问题)通用matlab程序 function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=ACATSP(C,NC_m ...
- Python利用A*算法解决八数码问题
资源下载地址:https://download.csdn.net/download/sheziqiong/86790565 资源下载地址:https://download.csdn.net/downl ...
- A*算法解决八数码问题 Java语言实现
A*算法解决八数码问题 Java语言实现 参考文章: (1)A*算法解决八数码问题 Java语言实现 (2)https://www.cnblogs.com/beilin/p/5981483.html ...
- 题目2:隐式图的搜索问题(A*算法解决八数码)
数据结构课程实践系列 题目1:学生成绩档案管理系统(实验准备) 题目2:隐式图的搜索问题(A*算法解决八数码) 题目3:文本文件单词的检索与计数(实验准备) 文章目录 数据结构课程实践系列 题目1:学 ...
- Astar、A星算法解决八数码问题--python实现
一.问题描述 数码问题又称9宫问题,与游戏"华容道"类似.意在给定的3*3棋格的8个格子内分别放一个符号,符号之间互不相同,余下的一格为空格.并且通常把8个符号在棋格上的排列顺序称 ...
- 广度优先算法解决8数码问题【c++】
8数码问题 (广度优先算法解决----c++) 8数码问题问题描述 八数码问题也称为九宫问题,在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格(空格用0来表示),空格 ...
- 【算法】模拟退火算法解决TSP问题的matlab实现
[算法]模拟退火算法解决TSP问题的matlab实现 参考文章: (1)[算法]模拟退火算法解决TSP问题的matlab实现 (2)https://www.cnblogs.com/wenyehoush ...
- 回溯算法解决八皇后_4皇后问题和使用回溯算法的解决方案
回溯算法解决八皇后 4-皇后问题 (4 - Queen's problem) In 4- queens problem, we have 4 queens to be placed on a 4*4 ...
- Python实现A*算法解决N数码问题
Python实现A*算法解决N数码问题 A*算法的描述 A*算法的步骤 问题描述 代码以及测试结果 算法优势 算法存在一些不足 A*算法的描述 A*算法是BFS的一个变种,它把原来的BFS算法的无启发 ...
- 【AFSA TSP】基于matlab人工鱼群算法求解旅行商问题【含Matlab源码 422期】
一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[TSP]基于matlab人工鱼群算法求解旅行商问题[含Matlab源码 422期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式2 ...
最新文章
- cmder 此时不应有 \Microsoft
- JqueryMobile- 搭建主模板
- [云炬创业基础笔记]第七张创业资源测试11
- 牛!又一顶级大厂开招.NET,5年35k!
- 计算机视觉招聘_INDEMIND|SLAM、计算机视觉、深度学习算法招聘(社招实习)
- 《软件测试》第五次作业
- VC++CopyFile函数的用法
- CVPR 2020 Oral |神奇的自监督场景去遮挡
- android 自定义指南针,如何在android中制作自定义指南针视图
- 手把手系列|风控建模中共线性的影响和处理(上)
- MyBatis(四)------MyBatis的生命周期及配置实例
- apache 压力测试工具 ab ,带post参数,token请求
- 本地上传文件到服务器
- 怎样快速实现两台电脑硬盘文件共享?
- SEM代码篇----R详细实现(SEM 2)
- 个人中心(修改密码)
- 2022-2028年全球与中国插座行业市场深度调研及投资预测分析
- ubuntu 添加中文拼音输入法【转载】
- Unity五子棋游戏设计 和简单AI实现(1)
- ffmpeg h264文件转mp4