数据结构实践项目二——隐式图的搜索问题(代码实现)

一、初始化

global olen;  %open表的长度
global clen;  %close表的长度
global time;  %循环次数
clen=0;
olen=1;
time=0;
target=input("请输入目标状态(以三阶方阵表示):"); 
%% 节点结构体
node.pre=zeros(3);
node.cur=input("请输入初始状态(以三阶方阵表示):");
node.num=1;
node.value=cost(node,target);
node.step=0;

openList(1)=node; %初始化open表
label=0; %循环停止标志
k=node;  %临时节点

二、代价评估函数

cost.m

function value=cost(node,target)
choice=2; 
%%  计算当前状态与目标状态八个数字的曼哈顿距离之和
if choice==1
    distance=0;
    for i=1:8
        [x,y]=find(node.cur==i);
        [x1,y1]=find(target==i);
        distance=distance+abs(x-x1)+abs(y-y1); 
    end
    value=distance;
end
%% 计算错位数个数
if choice==2
    count=0;
    count=sum(sum(node.cur~=target));
    value=count;
end
end
%% 计算欧式距离
if choice==3
    distance=0;
    for i=1:8
        [x,y]=find(node.cur==i);
        [x1,y1]=find(target==i);
        distance=distance+power(x-x1,2)+power(y-y1,2);
    end
    value=distance;
end

三、空格的移动操作

move.m

%% 移动操作,九个位置对应九种情况
function openList=move(op,cl,node,target)
global clen;
[x,y]=find(node.cur==0);
if x==1&&y==1
    openList=right(node,op,cl,target);
    openList=down(node,openList,cl,target);
elseif x==1&&y==2
    openList=left(node,op,cl,target);
    openList=right(node,openList,cl,target);
    openList=down(node,openList,cl,target);
elseif x==1&&y==3
    openList=left(node,op,cl,target);
    openList=down(node,openList,cl,target);
elseif x==2&&y==1
    openList=up(node,op,cl,target);
    openList=right(node,openList,cl,target);
    openList=down(node,openList,cl,target);
elseif x==2&&y==2
    openList=left(node,op,cl,target);
    openList=up(node,openList,cl,target);
    openList=right(node,openList,cl,target);
    openList=down(node,openList,cl,target);
elseif x==2&&y==3
    openList=left(node,op,cl,target);
    openList=up(node,openList,cl,target);
    openList=down(node,openList,cl,target);
elseif x==3&&y==1
    openList=up(node,op,cl,target);
    openList=right(node,openList,cl,target);
elseif x==3&&y==2
    openList=left(node,op,cl,target);
    openList=up(node,openList,cl,target);
    openList=right(node,openList,cl,target);
elseif x==3&&y==3
    openList=left(node,op,cl,target);
    openList=up(node,openList,cl,target);
end
end

%% 向右移动 
function openList=right(node,op,cl,target)
global olen;
olen=olen+1;
s=node;
[x,y]=find(s.cur==0);
t=s.cur(x,y+1);
s.cur(x,y+1)=0;
s.cur(x,y)=t;
s.num=olen;
op(olen).cur=s.cur;
op(olen).pre=node.cur;
op(olen).num=olen;
op(olen).value=cost(s,target); 
op(olen).step=s.step+1;
search(s,op,cl);
openList=op;
end

%% 向上移动
function openList=up(node,op,cl,target)
global olen;
olen=olen+1;
s=node;
[x,y]=find(s.cur==0);
t=s.cur(x-1,y);
s.cur(x-1,y)=0;
s.cur(x,y)=t;
s.num=olen; 
op(olen).cur=s.cur;
op(olen).pre=node.cur;
op(olen).num=olen;
op(olen).value=cost(s,target); 
op(olen).step=s.step+1;
search(s,op,cl);
openList=op;
end

%% 向左移动 
function openList=left(node,op,cl,target)
global olen;
olen=olen+1;
s=node; 
[x,y]=find(s.cur==0);
t=s.cur(x,y-1);
s.cur(x,y-1)=0;
s.cur(x,y)=t;
s.num=olen; 
op(olen).cur=s.cur;
op(olen).pre=node.cur;
op(olen).num=olen;
op(olen).value=cost(s,target);
op(olen).step=s.step+1; 
search(s,op,cl);
openList=op;
end

%% 向下移动
function openList=down(node,op,cl,target)
global olen;
olen=olen+1;
s=node; 
[x,y]=find(s.cur==0);
t=s.cur(x+1,y);
s.cur(x+1,y)=0;
s.cur(x,y)=t;
s.num=olen; 
op(olen).cur=s.cur;
op(olen).pre=node.cur;
op(olen).num=olen;
op(olen).value=cost(s,target); 
op(olen).step=s.step+1;
search(s,op,cl);
openList=op;
end

四、查重操作

search.m

%% 查找并去除状态重复的节点
function []=search(node,op,cl)
global olen;
global clen;
for i=1:olen-1
    if  op(i).cur==node.cur
        olen=olen-1;
        break;
    end
end
 
for i=1:clen-1
    if cl(i).cur==node.cur
        olen=olen-1;
        break;
    end
end
end

五、主函数

main.m

global olen;  %open表的长度
global clen;  %close表的长度
global time;  %循环次数
clen=0;
olen=1;
time=0;

%target=input("请输入目标状态(以三阶方阵表示):"); 
target=[0,1,2;3,4,5;6,7,8];
%% 节点结构体
node.pre=zeros(3);
%node.cur=input("请输入初始状态(以三阶方阵表示):");
node.cur=[1,2,3;4,5,6;7,8,0];
node.num=1;
node.value=cost(node,target);
node.step=0;
openList(1)=node; %初始化open表
label=0; %循环停止标志
k=node;  %临时节点

tic 
while label==0
    time=time+1;   
%% 寻找代价最小的节点
    for i=1:olen
        if (k.value+k.step)>=(openList(i).value+openList(i).step) 
            k=openList(i);
            x=i;
        end
    end 
 %% 访问过的节点加入close表
    clen=clen+1;
    closeList(clen)=k;
    closeList(clen).num=clen;
 %% 判断是否找到目标节点
    label=min(min(k.cur==target));
%% 扩展节点并删除open表中已访问的节点
    openList=move(openList,closeList,k,target);
    k.value=inf;
    openList(x)=[];
    olen=olen-1;
end
toc
%% 存储路径
b=0;
n=0;
y=target;
while 1
    for i=1:clen
        if y==zeros(3)
           b=1;
           break;
        end
        if closeList(i).cur==y
           t=closeList(i).num;
           n=n+1;
           index(n)=t;
           y=closeList(i).pre;
        end
    end
    if b==1
        break;
    end
end
%% 打印结果
fprintf('求解成功,共用步数:%d',size(index,2)-1);
        disp(" ");
disp("最佳路径为:")
for i=1:n
    if i==1
        disp("开始:")
    else
        fprintf("第");
        fprintf('%d',i-1);
        fprintf("步:");
        disp(" ");
    end
    disp(closeList(index(n+1-i)).cur);
end

———2021.3.3(gzc)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值