用A*算法解决八数码问题 MATLAB

1 篇文章 0 订阅
1 篇文章 0 订阅

代码:

bashuma.m

function []=bashuma
global e;  %open表计数
global i;  %close表计数
global m;  %循环次数计数
a=0;b=0;n=0;i=0;
e=1;m=0;

%初始化
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.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


open.m

%上下左右移动操作
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);

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);

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);

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);

search(s,op,cl);
open=op;
end

function fuc=valuefuc(f,dis)
  s1=0;
  [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


search.m

% 查询重复操作
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


valuefuc.m

function fuc=valuefuc(f,dis)
  s1=0;
  [x,y]=find(f.con==1);
  [x1,y1]=find(dis==1);
  s1=s1+abs(x-x1)+abs(y-y1); 
  [x,y]=find(f.con==2);
  [x1,y1]=find(dis==2);
  s1=s1+abs(x-x1)+abs(y-y1); 
  [x,y]=find(f.con==3);
  [x1,y1]=find(dis==3);
  s1=s1+abs(x-x1)+abs(y-y1); 
  [x,y]=find(f.con==4);
  [x1,y1]=find(dis==4);
  s1=s1+abs(x-x1)+abs(y-y1); 
  [x,y]=find(f.con==5);
  [x1,y1]=find(dis==5);
  s1=s1+abs(x-x1)+abs(y-y1); 
  [x,y]=find(f.con==6);
  [x1,y1]=find(dis==6);
  s1=s1+abs(x-x1)+abs(y-y1); 
  [x,y]=find(f.con==7);
  [x1,y1]=find(dis==7);
  s1=s1+abs(x-x1)+abs(y-y1); 
  [x,y]=find(f.con==8);
  [x1,y1]=find(dis==8);
  s1=s1+abs(x-x1)+abs(y-y1); 
  fuc=s1
end


运行结果:

 

思路:代码很复杂。。人工智能老师说要自己敲。。

 

 

 

 

 

 

 

include using namespace std; struct node{ int nodesun[4][4]; int pre; //上一步在队列中的位置 int flag ; //步数标识,表示当前的步数为有效的 int value; //与目标的差距 int x,y; //空格坐标 }queue[1000]; //移动方向数组 int zx[4]={-1,0,1,0}; int zy[4]={0,-1,0,1}; //当前步数 int top; int desti[4][4];//目标状态 int detect(struct node *p)//检查是否找到 {int i,j; for(i=1;i<4;i++) for(j=1;jnodesun[i][j]!=desti[i][j]) return 0; return 1; } //打印 void printlj() {int tempt; int i,j; tempt=top; while(tempt!=0) { for(i=1;i<4;i++) for(j=1;j<4;j++) {cout<<queue[tempt].nodesun[i][j]; if(j==3) cout<<" "<<endl; } tempt=queue[tempt].pre; } } //现在状态与目标状态有多少个不同位置 int VALUE(struct node *p) {int count=0; int i,j; for(i=1;i<4;i++) for(j=1;jnodesun[i][j]!=desti[i][j]) count++; return count; } void main() { //初始化 int i,j,m,n,f; int min=10; int temp,find=0,minnumber; top=1; for(i=1;i<4;i++) for(j=1;j<4;j++) {cout<<"请输入第"<<i<<"行"<<"第"<<j<<"列的值"<>temp; queue[1].nodesun[i][j]=temp; } cout<<"请输入初始状态的空格的位置(行)"<>temp; queue[1].x=temp; cout<<"请输入初始状态的空格的位置(列)"<>temp; queue[1].y=temp; queue[1].value=VALUE(&queue[1]); queue[1].pre=0; //上一步在队列中的位置 queue[1].flag=0; //目标状态 for(i=1;i<4;i++) for(j=1;j<4;j++) {cout<<"请输入目标状态第"<<i<<"行"<<"第"<<j<<"列的值"<>temp; desti[i][j]=temp; } //根据估价函数 while(!find&&top>0) { for(i=1;i<=top;i++) //////////////////////////////////////////// //min为上一图中与目标图有多少个元素不相同,queue[i]为当前图与目标图有多少个元素不相同通过这两个数的比较,就可以得出当前图较之上一图向目标图接近同时把当前的i记录下来进行下一步比较 {if(queue[i].value<min&&queue[i].flag==0) {minnumber=i;// min=queue[i].value; //还有多少不同的位数 } } queue[minnumber].flag=1; //表示此位有效 ////////////////////////////////////// // for(f=0;f=1&&i=1&&j<=3) {top++; ///////////////////////////////////////////// //位置交换 queue[top]=queue[minnumber]; queue[top].nodesun[m][n]=queue[minnumber].nodesun[i][j]; queue[top].nodesun[i][j]=0; /////////////////////////////////////// //空格移动方向 queue[top].x=i; queue[top].y=j; /////////////////////////////////////// queue[top].pre=minnumber; //上一步在队列中的位置 queue[top].value=VALUE(&queue[top]); //有多少位与目标不同 queue[top].flag=0; //标识位初始化 if(detect(&queue[top])) //检查是否为目标 {printlj(); //打印 find=1; //设找到标识位 break; } } } } }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的Anthony

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值