深度宽度优先搜索八数码Word文档下载推荐.docx
- 文档编号:21873645
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:19
- 大小:73.61KB
深度宽度优先搜索八数码Word文档下载推荐.docx
《深度宽度优先搜索八数码Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《深度宽度优先搜索八数码Word文档下载推荐.docx(19页珍藏版)》请在冰豆网上搜索。
4)+a[iii];
}*///将数组a转换为一个64位的整数b
#defineRTRANS(a,b)\
{\
longiii;
\
UINT64ttt=(a);
for(iii=NUM-1;
iii>
=0;
iii--)\
b[iii]=ttt&
0xf;
ttt>
>
=4;
}\
}//将一个64位整数a转换为数组b
//
typedefstructEP_NODE_Tag
{UINT64v;
//保存状态,每个数字占4个二进制位,可解决16数码问题
structEP_NODE_Tag*prev;
//父节点
structEP_NODE_Tag*small,*big;
}EP_NODE;
EP_NODEm_ar[MAX_NODE];
EP_NODE*m_root;
longm_depth;
//搜索深度
EP_NODEm_out[MAX_DEP];
//输出路径
longmove_gen(EP_NODE*node,EP_MOVE*move)
{longpz;
//0的位置
UINT64t=0xf;
for(pz=NUM-1;
pz>
pz--)
{if((node->
v&
t)==0)
{break;
//找到0的位置
}
t<
switch(pz)
{case0:
move[0].x=0;
move[0].y=1;
move[1].x=0;
move[1].y=3;
return2;
case1:
move[0].x=1;
move[0].y=0;
move[1].x=1;
move[1].y=2;
move[2].x=1;
move[2].y=4;
return3;
case2:
move[0].x=2;
move[1].x=2;
move[1].y=5;
case3:
move[0].x=3;
move[1].x=3;
move[1].y=6;
move[2].x=3;
case4:
move[0].x=4;
move[1].x=4;
move[2].x=4;
move[2].y=5;
move[3].x=4;
move[3].y=7;
return4;
case5:
move[0].x=5;
move[0].y=2;
move[1].x=5;
move[1].y=4;
move[2].x=5;
move[2].y=8;
case6:
move[0].x=6;
move[0].y=3;
move[1].x=6;
move[1].y=7;
case7:
move[0].x=7;
move[0].y=6;
move[1].x=7;
move[2].x=7;
case8:
move[0].x=8;
move[0].y=5;
move[1].x=8;
return0;
longmov(EP_NODE*n1,EP_MOVE*mv,EP_NODE*n2)
//走一步,返回走一步后的结果
charss[NUM];
RTRANS(n1->
v,ss);
XCHG(ss[mv->
x],ss[mv->
y]);
TRANS(ss,n2->
v);
longadd_node(EP_NODE*node,longr)
EP_NODE*p=m_root;
EP_NODE*q;
while(p)
{q=p;
if(p->
v==node->
v)return0;
elseif(node->
v>
p->
v)p=p->
big;
v<
small;
m_ar[r].v=node->
v;
m_ar[r].prev=node->
prev;
m_ar[r].small=NULL;
m_ar[r].big=NULL;
if(node->
q->
v)
{q->
big=&
m_ar[r];
small=&
return1;
/*得到节点所在深度*/
longget_node_depth(EP_NODE*node)
{longd=0;
while(node->
prev)
{d++;
node=node->
returnd;
/*返回值:
成功-返回搜索节点数,节点数不够-(-1),无解-(-2)*/
longbfs_search(char*begin,char*end)
{longh=0,r=1,c,i,j;
EP_NODEl_end,node,*pnode;
EP_MOVEmv[4];
//每个局面最多4种走法
TRANS(begin,m_ar[0].v);
TRANS(end,l_end.v);
m_ar[0].prev=NULL;
m_root=m_ar;
m_root->
small=NULL;
big=NULL;
while((h<
r)&
&
(r<
MAX_NODE-4))
{c=move_gen(&
m_ar[h],mv);
for(i=0;
i<
c;
i++)
{mov(&
m_ar[h],&
mv[i],&
node);
node.prev=&
m_ar[h];
if(node.v==l_end.v)
{pnode=&
node;
j=0;
while(pnode->
{m_out[j]=*pnode;
j++;
pnode=pnode->
m_depth=j;
returnr;
if(add_node(&
node,r))r++;
//只能对历史节点中没有的新节点搜索,否则会出现环
h++;
printf("
\rSearch...%9d/%d@%d"
h,r,get_node_depth(&
m_ar[h]));
if(h==r)
{return-2;
else
{return-1;
longcheck_input(char*s,chara,longr)
{longi;
r;
{if(s[i]==a-0x30)return0;
longcheck_possible(char*begin,char*end)
{charfs;
longf1=0,f2=0;
longi,j;
{fs=0;
for(j=0;
j<
i;
j++)
if((begin[i]!
=0)&
(begin[j]!
(begin[j]<
begin[i]))fs++;
f1+=fs;
fs=0;
{if((end[i]!
(end[j]!
(end[j]<
end[i]))fs++;
f2+=fs;
if((f1&
1)==(f2&
1))return1;
voidoutput(void)
{longi,j,k;
for(i=m_depth-1;
i>
i--)
{RTRANS(m_out[i].v,ss);
SIZE;
{for(k=0;
k<
k++)
{printf("
%2d"
ss[SIZE*j+k]);
\n"
);
intmain(void)
{chars1[NUM];
chars2[NUM];
longr;
chara;
请输入开始状态:
"
r=0;
while(r<
NUM)
{a=getchar();
if(a>
=0x30&
a<
0x39&
check_input(s1,a,r))
{s1[r++]=a-0x30;
%c"
a);
\n请输入结束状态:
check_input(s2,a,r))
{s2[r++]=a-0x30;
if(check_possible(s1,s2))
{r=bfs_search(s1,s2);
if(r>
=0)
查找深度=%d,所有的方式=%ld\n"
m_depth,r);
output();
elseif(r==-1)
没有找到路径.\n"
elseif(r==-2)
{printf("
这种状态变换没有路径到达.\n"
不确定的错误.\n"
不允许这样移动!
方法二:
用MATLAB实现
program8no_bfs;
{八数码的宽度优先搜索算法}
Const
Dir:
array[1..4,1..2]ofinteger{四种移动方向,对应产生式规则}
=((1,0),(-1,0),(0,1),(0,-1));
n=10000;
Type
T8no=array[1..3,1..3]ofinteger;
TList=record
Father:
integer;
{父指针}
dep:
byte;
{深度}
X0,Y0:
{0的位置}
State:
T8no;
{棋盘状态}
end;
Var
Source,Target:
List:
array[0..10000]ofTList;
{综合数据库}
Closed,open,Best:
integer{Best表示最优移动次数}
Answer:
{记录解}
Found:
Boolean;
{解标志}
procedureGetInfo;
{读入初始和目标节点}
vari,j:
begin
fori:
=1to3do
forj:
=1to3doread(Source[i,j]);
=1to3doread(Target[i,j]);
procedureInitialize;
{初始化}
varx,y:
Found:
=false;
Closed:
=0;
open:
=1;
withList[1]dobegin
State:
=Source;
dep:
Father:
Forx:
Fory:
ifState[x,y]=0thenBeginx0:
=x;
y0:
=y;
End;
FunctionSame(A,B:
T8no):
Boolean;
{判断A,B状态是否相等}
Vari,j:
Begin
Same:
Fori:
=1to3doforj:
=1to3doifA[i,j]<
B[i,j]thenexit;
=true;
End;
Functionnot_Appear(new:
tList):
boolean;
{判断new是否在List中出现}
vari:
not_Appear:
=1toopendoifSame(new.State,List[i].State)thenexit;
end;
procedureMove(n:
tList;
d:
varok:
boolean;
varnew:
tList);
{将第d条规则作用于n得到new,OK是new是否可行的标志}
X:
=n.x0+Dir[d,1];
Y:
=n.y0+Dir[d,2];
{判断new的可行性}
ifnot((X>
0)and(X<
4)and(Y>
0)and(Y<
4))thenbeginok:
exitend;
OK:
new.State:
=n.State;
{new=Expand(n,d)}
new.State[X,Y]:
new.State[n.x0,n.y0]:
=n.State[X,Y];
new.X0:
=X;
new.Y0:
=Y;
procedureAdd(new:
{插入节点new}
ifnot_Appear(new)thenBegin{如果new没有在List出现}
Inc(open);
{new加入open表}
List[open]:
=new;
procedureExpand(Index:
varn:
{扩展n的子节点}
new:
OK:
ifSame(n.State,Target)thenbegin{如果找到解}
=true;
Best:
=n.Dep;
Answer:
=Index;
Exit;
Fori:
=1to4dobegin{依次使用4条规则}
Move(n,i,OK,new);
ifnotokthencontinue;
new.Father:
=Index;
new.Dep:
=n.dep+1;
Add(new);
procedureGetOutInfo;
{输出}
procedureOutlook(Index:
integer);
{递归输出每一个解}
ifIndex=0thenexit;
Outlook(List[Index].Father);
withList[Index]do
=1to3dobegin
=1to3dowrite(State[i,j],'
'
writeln;
Writeln('
Total='
Best);
Outlook(Answer);
procedureMain;
{搜索主过程}
Repeat
Inc(Closed);
Expand(Closed,List[Closed]);
{扩展Closed}
Until(Closed>
=open)orFound;
ifFoundthenGetOutInfo{存在解}
elseWriteln('
noanswer'
{无解}
Begin
Assign(Input,'
input.txt'
ReSet(Input);
Assign(Output,'
Output.txt'
ReWrite(Output);
GetInfo;
Initialize;
Main;
Close(Input);
Close(Output);
End.
五、实验结果
六、实验总结
通过实验问题的求解过程就是搜索的过程,采用适合的搜索算法是关键的,因为对求解过程的效率有很大的影响,包括各种规则、过程和算法等推理技术。
八数码问题中,将牌的移动来描述规则,是一种相对较简单的方法。
用广度优先算法实现八数码问题,其实是一种比较费劲的方式;
然而深度优先将是一个很好的方法,利用深度优先不但减少了程序实现的时间,是一种不错的方式。
但最好的方式是启发式搜索方式实现,在很大程度上相对于前两种方式是一种非常好的实现方式,不但节省了时间,也节省了空间。
通过这次试验使我对搜索算法有了一定的了解,并对实现这个问题的执行过程有了更一步的认识。
也通过它解决了八数码问题,但在实际的过程中还存在很多问题,也看了一些辅助书籍,以后还要加强学习,加强理论与实际的练习。
总之,这次试验使我受益匪浅。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 深度 宽度 优先 搜索 数码