重排九宫格.docx
《重排九宫格.docx》由会员分享,可在线阅读,更多相关《重排九宫格.docx(14页珍藏版)》请在冰豆网上搜索。
重排九宫格
重排九宫格问题
一.问题描述
在3*3的方格棋盘上放置分别标有数字1,2,3,4,5,6,7,8的8张牌,初始状态为s0,目标状态为sg,可使用的算符有空格左移,空格上移,空格右移和空格下移,即它们只允许把位于空格左,上,右,下边的牌移入空格。
要求寻找从初始状态到目的状态的路径。
二.算法描述
(1)把初始节点S0放入OPEN表。
(2)如果OPEN表为空,则问题无解,退出。
(3)把OPEN表的第一个节点取出放入CLOSE表(记为节点n)。
(4)考察节点n是否为目标节点。
若是,则求得了问题的解,退出。
(5)若节点n不可扩展,则转第2步。
(6)扩展节点n,将其子节点放入OPEN表的尾部,并为每一个子节点都配置指向父节点的指针,然后转第2步。
三.实验结果
四.实验结果分析
应用广度优先搜索可得到如上图所示的从初始状态到目标状态的路径。
广度优先搜索盲目性较大,当目标节点距初始节点较远时将会产生许多无用节点,搜索效率低。
但只要问题有解,用广度优先搜索总可以得到解,而且得到的是路径最短的解。
五.源代码
#include
usingnamespacestd;
#include"classes.h"
charelement:
:
ebegin[3][3]={
{2,8,3},
{1,0,4},
{7,6,5}
};
charelement:
:
dest[3][3]={
{1,2,3},
{8,0,4},
{7,6,5}
};
doubleelement:
:
k=1;//ifyouchangethekval,youmaygetdifferentresult.
intmain(){
listopen,close;//thesearetwolistthatholdsthetreenode.
elementebegin(element:
:
ebegin);
mygraphG(&ebegin);
//step1
open.pushtop(&ebegin);
//G.add(&ebegin);-->theconstructionfunctiondiditverywell.
while
(1){
//step2
if(open.getnum()==0){
cout<<"Thisquestionhasnosolution."<break;
}
/*if(close.getnum()>362880){
cout<<"outofbounderror"<break;
}*/
//cout<"<//step3
element*n;
close.pushend(n=open.pop());
//step4
if(element:
:
reach(n)){
cout<<"solutiongot:
";
G.drawtree(n);
cout<<"Totalsteps:
"<layer<break;
}
//step5
element*M[4];
//extendthenode
M[0]=n->goup();
M[1]=n->godown();
M[2]=n->goleft();
M[3]=n->goright();
inti;
for(i=0;i<4;i++){
if(M[i]==NULL)continue;
if(!
G.exist(M[i])){
//a
G.add(M[i],n);
//M[i]->draw();
if(!
open.exist(M[i])&&!
close.exist(M[i]))
open.pushbyforder(M[i]);
}else{
//b&c
G.changeparent(M[i],n);
}
}
//7orderhasbeeendownininserting.
//8whenwereachedhere,wewillgotothefront.
}
system("pause");
return0;
}
classes.h
structpoint{
intx;
inty;
point(intpx,intpy){
x=px;y=py;
}
};
classelement{
public:
charm[3][3];
staticchardest[3][3];
staticcharebegin[3][3];
intlayer;
staticdoublek;
intf_val;
element(chars[3][3],intl=0){
layer=l+1;
for(inti=0;i<3;i++){
for(intj=0;j<3;j++){
m[i][j]=s[i][j];
}
}
this->f();
}
pointgetpos(){
for(inti=0;i<3;i++){
for(intj=0;j<3;j++){
if(m[i][j]==0)
returnpoint(i,j);
}
}
system("echounable&pause");
}
intf(){
intg=0;
for(inti=0;i<3;i++){
for(intj=0;j<3;j++){
if(m[i][j]==dest[i][j]){
g+=0;
}else{
g+=1;
}
}
}
f_val=(int)(layer+k*g);
returnf_val;
}
element*goup(){
pointp=this->getpos();
if(p.x>0){
element*pnew=newelement(m,layer);
pnew->m[p.x][p.y]=pnew->m[p.x-1][p.y];
pnew->m[p.x-1][p.y]=0;
returnpnew;
}
returnNULL;
}
element*godown(){
pointp=this->getpos();
if(p.x<2){
element*pnew=newelement(m,layer);
pnew->m[p.x][p.y]=pnew->m[p.x+1][p.y];
pnew->m[p.x+1][p.y]=0;
returnpnew;
}
returnNULL;
}
element*goleft(){
pointp=this->getpos();
if(p.y>0){
element*pnew=newelement(m,layer);
pnew->m[p.x][p.y]=pnew->m[p.x][p.y-1];
pnew->m[p.x][p.y-1]=0;
returnpnew;
}
returnNULL;
}
element*goright(){
pointp=this->getpos();
if(p.y<2){
element*pnew=newelement(m,layer);
pnew->m[p.x][p.y]=pnew->m[p.x][p.y+1];
pnew->m[p.x][p.y+1]=0;
returnpnew;
}
returnNULL;
}
staticboolreach(element*p){
for(inti=0;i<3;i++){
for(intj=0;j<3;j++){
if(p->m[i][j]!
=dest[i][j])
returnfalse;
}
}
returntrue;
}
voiddraw(){
cout<for(inti=0;i<3;i++){
cout<<'|';
for(intj=0;j<3;j++){
cout<<(int)m[i][j]<<'';
}
cout<<'|'<}
}
boolequals(constelement*p){
for(inti=0;i<3;i++){
for(intj=0;j<3;j++){
if(p->m[i][j]!
=this->m[i][j])
returnfalse;
}
}
returntrue;
}
};
template
classlist{
structnode{
T*ptr;
node*next;
};
node*base;//stackbasepointer
node*top;//stacktoppointer
intm_num;
public:
list(){
m_num=0;base=top=NULL;
}
boolpushtop(T*tp){
if(base==NULL){
base=top=(node*)malloc(sizeof(node));
base->next=NULL;
}else{
node*tmp;
tmp=(node*)malloc(sizeof(node));
tmp->next=top;
top=tmp;
}
top->ptr=tp;
m_num++;
returntrue;
}
boolpushbyforder(T*tp){
if(base==NULL){
base=top=(node*)malloc(sizeof(node));
base->next=NULL;
top->ptr=tp;
}else{
node*tmp,*find=top;
tmp=(node*)malloc(sizeof(node));
tmp->ptr=tp;
while(find!
=NULL){
if(tmp->ptr->f_valptr->f_val){
tmp->next=find->next;
find->next=tmp;
if(find==top){
top=tmp;
}
break;
}
find=find->next;
}
if(find==NULL){
base->next=tmp;
tmp->next=NULL;
base=tmp;
}
}
m_num++;
returntrue;
}
boolpushend(T*p){
if(base==NULL){
base=top=(node*)malloc(sizeof(node));
base->next=NULL;
}else{
node*tmp;
tmp=(node*)malloc(sizeof(node));
base->next=tmp;
tmp->next=NULL;
base=tmp;
}
base->ptr=p;
m_num++;
returntrue;
}
T*pop(){
if(m_num==0){
returnNULL;
}else{
T*tmp;
node*tobedel=top;
tmp=top->ptr;
top=top->next;
if(top==NULL){
base=NULL;
}
deletetobedel;
m_num--;
returntmp;
}
}
intgetnum(){
returnm_num;
}
T*operator[](intindex){
node*tmp=top;
while(index>0)index--,(tmp=tmp->next);
returntmp->ptr;
}
boolexist(T*p){
node*tmp=top;
while(NULL!
=tmp){
if(tmp->ptr->equals(p))
returntrue;
tmp=tmp->next;
}
returnfalse;
}
};
classmygraph{
//
structgnode{
element*ptr;
gnode*father;
//listchild;thisitemisnolongerneeded--,bymydesign
};
gnoderoot;
gnode**gnodelist;。
intnnodelist;
public:
mygraph(element*p){
root.ptr=p;
root.father=NULL;
gnodelist=(gnode**)malloc(sizeof(gnode*)*10240);
gnodelist[0]=&root;
nnodelist=1;
}
voidadd(element*pchild,element*pparent){
boolfind=false;
inti=0;
for(i=0;iif(pparent==gnodelist[i]->ptr){
find=true;
break;
}
}
if(!
find){
system("echolistErr:
No_parent_found&pause");
}
gnodelist[nnodelist]=(gnode*)malloc(sizeof(gnode));
gnodelist[nnodelist]->father=gnodelist[i];
gnodelist[nnodelist]->ptr=pchild;
nnodelist++;
}
boolexist(element*p){
for(inti=0;iif(gnodelist[i]->ptr==p){
returntrue;
}
}
returnfalse;
}
//boolhasparent(element*pchild){
//nowthatitbelogstothetree,youcancheckwhetherit'stheroot.
//returngnodelist[0]->ptr!
=pchild;
//}
voidchangeparent(element*pchild,element*newparent){
//findoutwhetherweshouldchangeit'sparentpointer
//anditwilldecidewhetherthechild'spointershouldbechange.
//maybeit'smeaningistochangethef_valofitschilds
boolfind=false;
inti;
for(i=0;iif(gnodelist[i]->ptr==pchild){
find=true;
break;
}
}
//wewillsurelyfindit,becauseicopiedthecodeinfunction'exist',hha.
if(gnodelist[i]->father->ptr->f_val>newparent->f_val){
//madeitthechildofasmallersection.
gnodelist[i]->father->ptr=newparent;//}
//elseIhavenothingtodo...
}
voiddrawtree(element*p){
boolfind=false;
inti;
for(i=0;iif(gnodelist[i]->ptr==p){
find=true;
break;
}
}
if(!
find)return;
gnode*tmp=gnodelist[i];
while(tmp!
=NULL){
tmp->ptr->draw();
cout<<"================"<tmp=tmp->father;
}
}
};
六.心得体会:
通过此次实验,加深了我对广度优先搜索的认识。
广度优先搜索盲目性较大,当目标节点距初始节点较远时将会产生许多无用节点,搜索效率低。
但广度优先搜索总可以得到解,而且得到的是路径最短的解。
在具体的编程实现中,如何定义节点的数据类型是个比较难的地方,编写比较长的程序对我来说还是一个比较艰巨的任务,以后还得多加强这方面的能力才行。