NOI 2.5基本算法之搜索 三维迷宫问题----分析

一、题目描述

总时间限制:

1000ms 内存限制: 65536kB 描述 You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides.
Is an escape possible? If yes, how long will it take?
输入 The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size).
L is the number of levels making up the dungeon.
R and C are the number of rows and columns making up the plan of each level.
Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a '#' and empty cells are represented by a '.'. Your starting position is indicated by 'S' and the exit by the letter 'E'. There's a single blank line after each level. Input is terminated by three zeroes for L, R and C.
输出 Each maze generates one line of output. If it is possible to reach the exit, print a line of the form
Escaped in x minute(s). where x is replaced by the shortest time it takes to escape.
If it is not possible to escape, print the line
Trapped! 样例输入 3 4 5
S....
.###.
.##..
###.#

#####
#####
##.##
##...

#####
#####
#.###
####E

1 3 3
S##
#E#
###

0 0 0
样例输出 Escaped in 11 minute(s).
Trapped!

题目大意:一道三维迷宫题目,长宽高<=30,样例输入中的数字(高 长 宽),如果输入“0 0 0”,程序结束。

“S”为入口,“E”为出口,“#”为墙,每移动一格(上下,左右,前后)都要一分钟,

输出最短需要的时间,“Escaped in 时间 minute(s).”

如果不能,则输出“Trapped!”。

 

二、分析

因为要求出最短的时间,一定要用广搜,就跟走出迷宫差不多,

建立四个队列s1,s2,s3,sum(可以把s1,s2,s3,合并成一个结构体队列)。

#include<cstdio>
#include<queue>
using namespace std;
int n,m,l,e,r,t,aa;
int sx[6]={-1,1,0,0,0,0},zy[6]={0,0,-1,1,0,0},qh[6]={0,0,0,0,-1,1};//方向数组
char a[35][35][35];
bool f;

然后再开始写广搜,

广搜代码如下

void bfs()
{
	f=0;
	int k1,k2,k3;
	while(!s1.empty())
	{
		for(int i=0;i<=5;i++)
		{
			if(s1.back()==e&&s2.back()==r&&s3.back()==t){
				f=1;
				break;
			}
			k1=s1.front()+sx[i];k2=s2.front()+zy[i];k3=s3.front()+qh[i];
			if(k1>=1&&k1<=n&&k2>=1&&k2<=m&&k3>=1&&k3<=l&&a[k1][k2][k3]!='#'){
				s1.push(k1);
				s2.push(k2);
				s3.push(k3);
				sum.push(sum.front()+1);
				a[k1][k2][k3]='#';
			}
		}
		if(f==1)
			break;
		s1.pop();
		s2.pop();
		s3.pop();
		sum.pop();
	}
	if(f==1)
		aa=sum.back();
	if(f==0)
		aa=0;
	return;
}

 

主程序的代码很简单,就是进行初始化和输入输出。

但是要注意,在每次循环之前要把队列pop()清空。

int i,j,k,q,w,qw;
	while(scanf("%d %d %d\n",&n,&m,&l)==3){
		if(n==0&&m==0&&l==0)
			break;
		while(!s1.empty())
			s1.pop();
		while(!s2.empty())
			s2.pop();
		while(!s3.empty())
			s3.pop();
		while(!sum.empty())
			sum.pop();
		for(i=1;i<=n;i++){
			//输入,找起点和终点
		}
		a[q][w][qw]='#';
		//元素入队
		aa=0;
		bfs();
		if(aa!=0)
			printf("Escaped in %d minute(s).\n",aa);
		if(aa==0)
			printf("Trapped!\n");
	}


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前面几日我重新实现了迷宫的自动生成方法,并且添加了迷宫自动寻路方法。有了一个独立于GUI的迷宫库,我开始迫不及待地实现三维迷宫了! 下面是我在开发迷宫程序中遇到的问题。 1、怎样将迷宫类的行和列映射到真实的三维坐标中?迷宫应该用哪个参考系来描述? 其实我在制作的时候为了简化,将二维迷宫的左上角与三维的原点重合,二维迷宫的右对应三维的X轴正方向,迷宫的下对应Z轴的正方向。 2、迷宫的“上、下、左、右”在三维中应该叫做什么? 在确定好迷宫的位置后,我们将迷宫的上对应Z轴的负半轴,下对应Z轴的正半轴,左对应X轴的负半轴,右对应Y轴的正半轴。 3、三维点绘制顺序以及OpenGL裁剪模式造成的一些面不可见问题。 这个问题是我在编写二维迷宫没有想到的。主要是因为二维迷宫中描述墙是用一条直线,而到了三维则是一个面。由于在OpenGL中有裁剪模式可以选择,我使用了 glFrontFace( GL_CW ); // 顺时针的绘制为正面 glEnable( GL_CULL_FACE ); // 剔除不是正面的面 进行设定,也就是说,所有在摄像机看来是逆时针绘制的图形都无法显示。因此我不得不用同样的顶点绘制两个面。下面是相关的函数: void DrawInnerWall( Point3F& p1, Point3F& p2, Point3F& p3, Point3F& p4 ) { glTexCoord2f( 0.0f, 1.0f ); glVertex3fv( p1 ); glTexCoord2f( 1.0f, 1.0f ); glVertex3fv( p2 ); glTexCoord2f( 1.0f, 0.0f ); glVertex3fv( p3 ); glTexCoord2f( 0.0f, 0.0f ); glVertex3fv( p4 ); } void DrawOuterWall( Point3F& p1, Point3F& p2, Point3F& p3, Point3F& p4 ) { glTexCoord2f( 1.0f, 1.0f ); glVertex3fv( p1 ); glTexCoord2f( 0.0f, 1.0f ); glVertex3fv( p2 ); glTexCoord2f( 0.0f, 0.0f ); glVertex3fv( p3 ); glTexCoord2f( 1.0f, 0.0f ); glVertex3fv( p4 ); } 在编写这些函数的时候尤其注意纹理坐标的绘制顺序。可以在纸上绘制一个草图。下面是我调用的代码: if ( Cell_UpWall( cell ) ) { DrawInnerWall( p8, p7, p3, p4 ); DrawOuterWall( p7, p8, p4, p3 ); } 4、怎样设置阻挡? 设置阻挡的基本原则还是先检测后执行。首先我先尝试着执行走一步,再判断这一步是不是出现了越界问题。如果出现了越界问题,那么不执行这一步,否则执行这一步。为了不让我们无限地靠近墙,我设定了一个gap,即摄像机必须与墙保持gap的距离。 下面是我相关的代码: bool View3D::CanGo( Maze& maze, float step ) { static float gap = m_CellSize.w / 8.0f;// 摄像机与墙最近不能超过的间隔 const Point3F& pos = m_Camera.Pos( ); Point3F tryPos; if ( pos.y > 0 && pos.y ( row - 1 ) * m_CellSize.w ); if (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值