A*搜索算法 MATLAB

寻路问题常见于各类游戏中角色寻路、三维虚拟场景中运动目标的路径规划,机器人寻路等多个应用领域。迷宫寻路问题是在以方格表示的地图场景中,对于给定的起点,终点和障碍物(墙),如何找到一条从起点开始避开障碍物到达终点的最短路径。

假设在一个nxm的迷宫里,入口坐标和出口坐标分别为(1,1)和(5,5),每一个坐标点有两种可能:0或1,其中0表示该位置允许通过,1表示该位置不允许通过。迷宫图如下:

以迷宫寻路问题为例实现A*算法的求解程序,要求设计两种不同的估价格函数。

先将迷宫数组化:我将其周围全都加了一面墙,即一圈都是1,如下图所示:

然后再来进行后续的操作。

迷宫内的每一个点都用一个结构体来表示,结构体内包含了六个变量:jiedian=struct('node',1,'top',1,'bottom',1,'left',1,'right',1,'length',0);

1代表是墙不能通过,0代表可以通过的路,length是该节点已经走过的路程。

初始化迷宫表:

for i=2:6

    for j=2:6  %初始化

        migongs(i,j).node=migong(i,j);

        migongs(i,j).top=migong(i-1,j);

        migongs(i,j).bottom=migong(i+1,j);

        migongs(i,j).left=migong(i,j-1);

        migongs(i,j).right=migong(i,j+1);

        migongs(i,j).length=0;

    end

end

一共七行七列,因为最外层是墙所以不用初始化。

创建一个open表来记录要扩展的节点,一个变量openodenum来记录open表中还剩余的节点,一个变量totlenode来记录所有的增加到open表中的节点数,一个变量expand来记录扩展过的节点数。开始时变量状态如下:

open=[2;2];  %表示open表中的第一个节点是迷宫表中的第2行,第2列

openodenum=1;

totlenode=1;

expand=0;

Open表中最开始记录的是start节点,写一个while循环,从start节点开始扩展,每扩展一个节点,expand就+1,如果被扩展节点的周围有可扩展的节点,就把它加入到open表中,并且要记录其走过的路程为上一个节点走过的路程+1。

没有创建close表因为每次扩展一个节点时我都要把他的node变为1,并且其周围节点的相应边也变为1,也就是说被扩展过了不能再扩展了,比每次循环去找close表中的节点要快一点。

扩展完一个节点后,将open表中的所有节点前移,也即删掉第一个扩展完的节点,然后再从open表中选出下一个要扩展的节点,把它的位置换到open表中的第一个位置,此处就需要自己设计一个启发式函数来找到最优的该扩展的节点。

就这样在while中循环,每次扩展一个算法认为是最优的节点来找最优的路,从而完成迷宫寻路问题。

关于估价函数,此处我写了三个:

对于书上的迷宫图:

  1. F=(6-open(1,1))+(6-open(2,1) 只比较open表中的节点到终点的横纵坐标差值的和。
  2. F=(open(1,1)-6)*(open(1,1)-6)+(open(2,1)-6)*(open(2,1)-6)  只比较open表中的节点到终点的直线距离
  3. G=migongs((open(1,1)),(open(2,1))).length;  %已经走过的路程

H=6-open(1,1)+6-open(2,1);                  %估计剩余的路程

F=G+H    比较已经走过的路程和估计剩余的路程的和。

运行书上的那个较小的迷宫图时,此三种估价函数所寻找出来的结果都差不多,最终如下图所示:

    其运行时间也都在0.04-0.1之间,不能体现(3)的优点,然后换一个大的迷宫:

    在上图的迷宫进行寻路时,估价函数(3)就显示出了它优点,在用前两个估价函数进行搜索时,会产生局部最优解,不能找到全局最优解,且其产生的节点也比较多,寻路时间比较长,如下图:

    第三种估价函数比前两种估价函数要好,不管产生多少节点,它总能够产生最优解,但可能在非常复杂的迷宫中会用较多的时间来寻路,但只要有解,它总能找到解,且是最优解。

    其过程如下图所示:

                           

此为第三种估价函数所运行出来的结果              此为第二种估价函数运行出来的结果

st=cputime;

jiedian=struct('node',1,'top',1,'bottom',1,'left',1,'right',1,'length',0);

migong=[1,1,1,1,1,1,1,1,1,1,1,1,1;

        1,0,0,0,0,0,0,0,1,1,1,0,1;

        1,1,0,1,0,1,1,0,1,1,0,0,1;

        1,0,0,1,1,1,1,0,0,0,0,0,1;

        1,0,1,0,0,0,1,0,1,1,0,0,1;

        1,0,1,0,1,0,1,0,1,1,1,0,1;

        1,0,1,0,1,0,1,0,0,1,0,0,1;

        1,0,1,0,1,0,1,1,0,0,0,1,1;

        1,0,1,0,1,0,1,1,0,1,1,0,1;

        1,0,1,0,1,0,0,0,0,1,0,0,1;

        1,0,1,0,1,1,1,1,1,1,1,0,1;

        1,0,0,0,0,0,0,0,0,0,0,0,1;

        1,1,1,1,1,1,1,1,1,1,1,1,1]

migongs=[jiedian,jiedian,jiedian,jiedian,jiedian,jiedian,jiedian;

         jiedian,jiedian,jiedian,jiedian,jiedian,jiedian,jiedian;

         jiedian,jiedian,jiedian,jiedian,jiedian,jiedian,jiedian;

         jiedian,jiedian,jiedian,jiedian,jiedian,jiedian,jiedian;

         jiedian,jiedian,jiedian,jiedian,jiedian,jiedian,jiedian;

         jiedian,jiedian,jiedian,jiedian,jiedian,jiedian,jiedian;

         jiedian,jiedian,jiedian,jiedian,jiedian,jiedian,jiedian];

open=[2;2];

openodenum=1;

totlenode=1;

expand=0;

for i=2:12

    for j=2:12  %初始化

        migongs(i,j).node=migong(i,j);

        migongs(i,j).top=migong(i-1,j);

        migongs(i,j).bottom=migong(i+1,j);

        migongs(i,j).left=migong(i,j-1);

        migongs(i,j).right=migong(i,j+1);

        migongs(i,j).length=0;

    end

end

while(openodenum>0)  %扩展节点

        migongs(open(1,1),open(2,1)).node=1;

        disp(['扩展节点:','(',num2str(open(1,1)-1),',',num2str(open(2,1)-1),')'])

        expand=expand+1;

        if((open(1,1))==12&&open(2,1)==12)

                disp('成功!')

                totlenode

                expand

                break;

        end

        if(migongs(open(1,1),open(2,1)).top==0)

            migongs(open(1,1)-2,open(2,1)).bottom=1;

            migongs(open(1,1)-1,open(2,1)).bottom=1;

            migongs(open(1,1)-1,open(2,1)-1).right=1;

            migongs(open(1,1)-1,open(2,1)+1).left=1;

            migongs(open(1,1)-1,open(2,1)).length=migongs(open(1,1),open(2,1)).length+1;

            openodenum=openodenum+1;

            open(1,openodenum)=open(1,1)-1;

            open(2,openodenum)=open(2,1);

            totlenode=totlenode+1;

            x=open(1,1)-1-1;

            y=open(2,1)-1;

            disp(['增加节点:','(',num2str(x),',',num2str(y),')'])

        end

        if(migongs(open(1,1),open(2,1)).bottom==0)

            migongs(open(1,1)+2,open(2,1)).top=1;

            migongs(open(1,1)+1,open(2,1)).top=1;

            migongs(open(1,1)+1,open(2,1)-1).right=1;

            migongs(open(1,1)+1,open(2,1)+1).left=1;

            migongs(open(1,1)+1,open(2,1)).length=migongs(open(1,1),open(2,1)).length+1;

            openodenum=openodenum+1;

            open(1,openodenum)=open(1,1)+1;

            open(2,openodenum)=open(2,1);

            totlenode=totlenode+1;

            x=open(1,1)+1-1;

            y=open(2,1)-1;

            disp(['增加节点:','(',num2str(x),',',num2str(y),')'])

        end

        if(migongs(open(1,1),open(2,1)).left==0)

            migongs(open(1,1),open(2,1)-2).right=1;

            migongs(open(1,1),open(2,1)-1).right=1;

            migongs(open(1,1)-1,open(2,1)-1).bottom=1;

            migongs(open(1,1)+1,open(2,1)+1).top=1;

            migongs(open(1,1),open(2,1)-1).length=migongs(open(1,1),open(2,1)).length+1;

            openodenum=openodenum+1;

            open(1,openodenum)=open(1,1);

            open(2,openodenum)=open(2,1)-1;

            totlenode=totlenode+1;

            x=open(1,1)-1;

            y=open(2,1)-1-1;

            disp(['增加节点:','(',num2str(x),',',num2str(y),')'])

        end

        if(migongs(open(1,1),open(2,1)).right==0)

            migongs(open(1,1),open(2,1)+2).left=1;

            migongs(open(1,1),open(2,1)+1).left=1;

            migongs(open(1,1)-1,open(2,1)+1).bottom=1;

            migongs(open(1,1)+1,open(2,1)+1).top=1;

            migongs(open(1,1),open(2,1)+1).length=migongs(open(1,1),open(2,1)).length+1;

            openodenum=openodenum+1;

            open(1,openodenum)=open(1,1);

            open(2,openodenum)=open(2,1)+1;

            totlenode=totlenode+1;

            x=open(1,1)-1;

            y=open(2,1)+1-1;

            disp(['增加节点:','(',num2str(x),',',num2str(y),')'])

        end

        for n=1:openodenum-1

            open(1,n)=open(1,n+1);

            open(2,n)=open(2,n+1);

        end

        openodenum=openodenum-1;

        tempi=0;

        tempj=0;

        G=migongs((open(1,1)),(open(2,1))).length; %已经走过的路程  F=G+H

        H=6-open(1,1)+6-open(2,1);                 %估计剩余的路程

        Gx=migongs((open(1,n)),(open(2,n))).length;

        Hx=6-open(1,n)+6-open(2,n);

        for n=1:openodenum

            if(G+H>Gx+Hx)         %找出F最小的那个节点继续扩展

                tempi=open(1,1);

                tempj=open(2,1);

                open(1,1)=open(1,n);

                open(2,1)=open(2,n);

                open(1,n)=tempi;

                open(2,n)=tempj;

            end

        end

end

et=cputime-st

 

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值