迷宫求解火车重排.docx
- 文档编号:22993022
- 上传时间:2023-04-29
- 格式:DOCX
- 页数:28
- 大小:49.53KB
迷宫求解火车重排.docx
《迷宫求解火车重排.docx》由会员分享,可在线阅读,更多相关《迷宫求解火车重排.docx(28页珍藏版)》请在冰豆网上搜索。
迷宫求解火车重排
第三章数据结构实验报告
实验名称:
迷宫求解
实验类型:
设计性实验
1.问题描述
问题描述
这是心理学中的一个经典问题。
心理学家把一只老鼠从一个无顶盖的大盒子的入口处放入,让老鼠自行找到出口出来。
迷宫中设置很多障碍阻止老鼠前行,迷宫唯一的出口处放有一块奶酪,吸引老鼠找到出口。
简而言之,迷宫问题是解决从布置了许多障碍的通道中寻找出路的问题。
本题设置的迷宫如图1所示。
图1迷宫示意图
迷宫四周设为墙;无填充处,为可通处。
设每个点有四个可通方向,分别为东、南、西、北。
左上角为入口。
右下角为出口。
迷宫有一个入口,一个出口。
设计程序求解迷宫的一条通路。
2.数据结构设计
栈类的实现:
template
classStack
{
public:
Stack()
{
capacity=STACK_SIZE;
base=newType[capacity];
top=0;
}
~Stack()
{
capacity=0;
delete[]base;
base=NULL;
top=0;
}
public:
boolisfull()const
{
returntop>=capacity;
}
boolisempty()const
{
returntop==0;
}
voidpush(Type&x)
{
if(!
isfull())
{
base[top++]=x;
}
}
voidpop()
{
if(!
isempty())
{
top--;
}
}
Typegettop()const
{
if(!
isempty())
{
returnbase[top-1];
}
}
private:
enum{STACK_SIZE=100};
Type*base;
size_ttop;
size_tcapacity;
};
方向的存储采用枚举类型:
typedefenum
{
RIGHT=1,
DOWN,
LEFT,
UP,
}DIR;
迷宫及求解后的迷宫采用二维数组存储:
typedefintMaze[ROW][COL];//10x10的二维数组模拟迷宫
迷宫中点的实现:
typedefstructPos//表示位置
{
intx;
inty;
booloperator==(constPos&p)
{
return((x==p.x)&&(y==p.y));
}
}Pos;
迷宫中人的模拟:
typedefstructMan//模拟人
{
Pospos;
DIRdi;
}Man;
3.算法设计
系统输出迷宫通路,迷宫在程序中设定。
(1)参数给出当前位置及方向,返回下一位置:
PosNextPos(Pospos,DIRdi)
{
switch(di)
{
caseRIGHT:
pos.y+=1;
break;
caseDOWN:
pos.x+=1;
break;
caseLEFT:
pos.y-=1;
break;
caseUP:
pos.x-=1;
break;
}
returnpos;
}
(2)迷宫求解:
boolPassMaze(Mazemaze,Posstart,Posend)
{
Manman;//posdi
Stack
Poscurpos=start;
do//重复探索直至curpos==end找到出口,或者栈变空(没有任何一条通路)
{
if(Pass(maze,curpos))//如果当前点curpos能通过则将man的位置标记到此点,设置默认探索方向从RIGH开始
{
man.pos=curpos;
man.di=RIGHT;//默认从RIGHT开始探索
FootMaze(maze,man.pos);
cout< if(curpos==end) returntrue; st.push(man); curpos=NextPos(man.pos,man.di); } else { if(! st.isempty()) { man=st.gettop(); while(man.di==UP&&! st.isempty()) {//如果curpos不能通过,且man周围的点都探索完毕,人就往后退 st.pop(); //MarkMaze(maze,man.pos); if(! st.isempty()) { man=st.gettop(); } else//栈空了说明回到出口了,此迷宫没有通路 { returnfalse; } } if(man.di { st.pop(); man.di=(DIR)(man.di+1); st.push(man); curpos=NextPos(man.pos,man.di); } } } } while(! st.isempty()); returnfalse; } (2)迷宫通路的输出在模拟走迷宫中实现,与迷宫通路的标记同时完成: voidFootMaze(Mazemaze,Pospos) { maze[pos.x][pos.y]=2; cout<<"("< } 4.界面设计 迷宫为程序设定,界面输出初始迷宫以及迷宫通路。 5.运行、测试与分析 (1)运行程序,显示初始迷宫,如图。 图1.1启动界面 (2)显示迷宫通路,如图。 6.实验收获及思考 本程序考察了我对栈的应用,运用回溯解决迷宫问题。 通过对此程序的实现,加强了我对栈的理解,对迷宫问题的理解。 但在算法上还存在一些问题,如对多通路迷宫只能输出单通路的问题。 7.源码 #include #include usingnamespacestd; template classStack { public: Stack() { capacity=STACK_SIZE; base=newType[capacity]; top=0; } ~Stack() { capacity=0; delete[]base; base=NULL; top=0; } public: boolisfull()const { returntop>=capacity; } boolisempty()const { returntop==0; } voidpush(Type&x) { if(! isfull()) { base[top++]=x; } } voidpop() { if(! isempty()) { top--; } } Typegettop()const { if(! isempty()) { returnbase[top-1]; } } private: enum{STACK_SIZE=100}; Type*base; size_ttop; size_tcapacity; }; ///////////////////////////////////////////// #defineROW10 #defineCOL10 typedefenum { RIGHT=1, DOWN, LEFT, UP, }DIR; typedefintMaze[ROW][COL];//10x10的二维数组模拟迷宫 //表示位置 typedefstructPos { intx; inty; booloperator==(constPos&p) { return((x==p.x)&&(y==p.y)); } }Pos; //模拟人 typedefstructMan { Pospos; DIRdi; }Man; voidShowMaze(Mazemaze) { for(inti=0;i<10;++i) { for(intj=0;j<10;++j) { cout< } cout< } } boolPass(Mazemaze,Pospos) { returnmaze[pos.x][pos.y]==0; } //将能走通的位置标记为2 voidFootMaze(Mazemaze,Pospos) { maze[pos.x][pos.y]=2; } PosNextPos(Pospos,DIRdi) { switch(di) { caseRIGHT: pos.y+=1; break; caseDOWN: pos.x+=1; break; caseLEFT: pos.y-=1; break; caseUP: pos.x-=1; break; } returnpos; } boolPassMaze(Mazemaze,Posstart,Posend) { Manman;//posdi Stack Poscurpos=start; do//重复探索直至curpos==end找到出口,或者栈变空(没有任何一条通路) { if(Pass(maze,curpos))//如果当前点curpos能通过则将man的位置标记到此点,设置默认探索方向从RIGH开始 { man.pos=curpos; man.di=RIGHT;//默认从RIGHT开始探索 FootMaze(maze,man.pos); if(curpos==end) returntrue; st.push(man); curpos=NextPos(man.pos,man.di); } else { if(! st.isempty()) { man=st.gettop(); while(man.di==UP&&! st.isempty())//如果curpos不能通过,且man周围的点都探索完毕,人就往后退 { st.pop(); //MarkMaze(maze,man.pos); if(! st.isempty()) { man=st.gettop(); } else//栈空了说明回到出口了,此迷宫没有通路 { returnfalse; } } if(man.di { st.pop(); man.di=(DIR)(man.di+1); st.push(man); curpos=NextPos(man.pos,man.di); } } } }while(! st.isempty()); returnfalse; } intmain() { Posstart={0,1}; Posend={9,8}; Mazemaze= { {1,0,1,1,1,1,1,1,1,1}, {1,0,1,1,1,1,0,0,0,1}, {1,0,1,1,1,1,0,1,1,1}, {1,0,1,0,0,0,0,0,0,1}, {1,0,0,0,1,1,0,1,0,1}, {1,1,1,1,1,1,0,1,0,1}, {1,1,0,0,0,0,0,0,0,1}, {1,1,1,1,1,0,1,1,0,1}, {1,1,1,0,0,0,0,1,0,1}, {1,1,1,1,1,1,0,0,0,1} }; ShowMaze(maze); if(! PassMaze(maze,start,end)) { cout<<"没有出路! "< return0; } cout<<"-------------------"< ShowMaze(maze); } 实验名称: 火车车厢重排问题 实验类型: 设计性实验 1.问题描述 一列货运列车共有n节车厢,每节车厢将停放在不同的车站。 假定n个车站的编号分别为1~n,即货运列车按照第n站至第1站的次序经过这些车站。 为了便于从列车上卸掉相应的车厢,车厢的编号应与车站的编号相同,这样,在每个车站只要卸掉最后一节车厢。 所以,给定任意次序的车厢,必须重新排列它们。 车厢的重排工作可以通过转轨站完成。 在转轨站中有一个入轨、一个出轨和k个缓冲轨,缓冲轨位于入轨和出轨之间。 假定缓冲轨按先进先出的方式运作,设计算法解决火车车厢重排问题。 2.数据结构设计 本程序采用队列实现,队列的实现: template structQueue { Tq[MAX_ARR]; intfront,end;//队列头、队列尾标记 Queue()//初始队列 { front=0; end=0; } TFront()//返回队列头 { if(front returnq[front]; return-1; } TBack()//返回队列尾 { if(front returnq[end-1]; return-1; } TSize(){//返回队列大小 return(end-front); } TPop()//队列头出队列,并返回队列头 { Ttemp=q[front]; q[front++]=0; returntemp; } voidPush(Ta)//入队列 { q[end++]=a; } boolEmpty()//队列判空 { returnfront>=end; } voidOutput(intn)//队列输出,用于缓冲轨输出 { cout<<"Bufferrail["< "< for(inti=front;i! =end;i++) { cout< } cout< } }; 3.算法设计 程序实现包括缓冲轨的选择算法以及重排算法 (1)缓冲轨的选择算法: intMax(Queue { intflag=-1;//空缓冲轨标记 intflag2=-1;//有无缓冲轨可用标记 inttemp=0;//初始标记 for(intj=0;j { if(buff[j].Empty()){flag=j;}//若有空缓冲轨则记录 elseif((j>0)&&(buff[j].Back() {//若缓冲轨尾车厢小于火车车厢且为缓冲轨中最大则记录 temp=j; flag2++; } } if(flag2! =-1)returntemp;//若有可用非空缓冲轨则返回该缓冲轨 elseif(flag2==-1&&flag! =-1)returnflag;//若缓冲轨均空则返回空缓冲轨 elsereturn-1;//否则返回-1 } (2)车厢重排: voidRail(intn,intk)//n为车厢长度,k为缓冲轨个数 { Queue Queue Queue cout<<"Pleaseinputtheorderofcompartment"< for(inti=0;i { inttemp; cin>>temp; prail.Push(temp); } while(! (rail.Size()==n))//若出轨火车车厢数等于如归火车车厢数则跳出循环 { {//缓冲轨出轨判断 intflag=0;//出轨标记 for(intj=0;j { if(buff[j].Front()==(rail.Back()+1))//若缓冲轨头车厢满足出轨条件 { rail.Push(buff[j].Front());//缓冲轨头车厢出轨 cout<<"Bufferrail["< flag=1;//出队列标记 break; } } if(flag==1)continue;//进行下一车厢判断 } if(prail.Front()==1)//头车厢处理 { cout<<"compartment"< rail.Push(prail.Front());//入轨车厢直接出轨 prail.Pop();//出队列 continue; } if(prail.Front()==(rail.Back()+1))//其余车厢处理 { cout<<"compartment"< rail.Push(prail.Front());//入轨车厢直接出轨 prail.Pop();//出队列 continue; } if(Max(buff,k,prail.Front())! =-1){//判断是否有可用缓冲轨 cout<<"compartment"< buff[Max(buff,k,prail.Front())].Push(prail.Front());//入缓冲轨 cout<<"compartment"< continue; } else{ cout<<"noanswer"< break; } } } 4.界面设计 初始界面提示输入车厢数及缓冲轨数,输入后输出求解过程。 5.运行、测试与分析 (1)运行程序,如图。 图1.1启动界面 (2)显示求解过程,如图。 6.实验收获及思考 本程序考察了对队列的应用,以及对复杂过程的分解及处理。 通过本次实验强化了对队列的使用以及复杂的逻辑分析。 算法能解决问题,但在时间性能上略有不足,需要我进一步的改进。 7.源码 #include usingnamespacestd; constintMAX_ARR=10000; template structQueue { Tq[MAX_ARR]; intfront,end; Queue() { front=0; end=0; } TFront() { if(front returnq[front]; return-1; } TBack() { if(front returnq[end-1]; return-1; } TSize(){ return(end-front); } TPop() { Ttemp=q[front]; q[front++]=0; returntemp; } voidPush(Ta) { q[end++]=a; } boolEmpty() { returnfront>=end; } voidOutput(intn) { cout<<"Bufferrail["< "< for(inti=front;i! =end;i++) { cout< } cout< } }; intMax(Queue { intflag=-1; intflag2=-1; inttemp=0; for(intj=0;j { if(buff[j].Empty()){flag=j;} elseif((j>0)&&(buff[j].Back() temp=j; flag2++; } } if(flag2! =-1)returntemp; else
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 迷宫 求解 火车 重排