题目86:胜利大逃亡

//http://ac.jobdu.com/problem.php?cid=1040&pid=85
#include <stdio.h>
#include <queue>
using namespace std;
struct N             //状态结构体
{
	int x,y,z;       //位置坐标
	int t;           //所需时间
};
bool mark[51][51][51]; //标记数组,扩展出(x,y,z)之后记为true,再次扩展出来后直接丢弃
int maze[51][51][51];  //保存立方体信息  
queue<N> Q;            //队列中元素是状态(x,y,z,t)    
int go[][3]=          //坐标变换数组,(x,y,z)->(x+go[i][0],y+go[i][1],z+go[i][2])
{
	1,0,0,
	-1,0,0,
	0,1,0,
	0,-1,0,
	0,0,1,
	0,0,-1,
};
int BFS(int a,int b,int c)  //广度优先搜索,返回到达目的点的最少耗时
{
  while (Q.empty()==false)  //当仍有元素可以扩展时循环
  {
    N now=Q.front();
	Q.pop();
	for (int i=0;i<6;i++)   //依次扩展6个相邻节点
	{
      int nx=now.x+go[i][0];
	  int ny=now.y+go[i][1];
	  int nz=now.z+go[i][2];
	  
	  if (nx<0 || nx>=a || ny<0 || ny>=b || nz<0 || nz>=c )
	  {
		  continue;         //若新坐标再正方体外,丢弃该坐标
	  }
	  if (maze[nx][ny][nz]==1)
	  {
		  continue;         //若新坐标为墙,丢弃  
	  }
	  if (mark[nx][ny][nz]==true)
	  {
		  continue;         //若该状态已经得到过,则丢弃,因为时间必定大于上次
	  }
      
	  N tmp;               //新状态
	  tmp.x=nx;
	  tmp.y=ny;
	  tmp.z=nz;
	  tmp.t=now.t+1;
	  Q.push(tmp);         //该状态放入队列,因为广度优先按照被查找到的顺序依次扩展下一层
	  mark[nx][ny][nz]=true; //标记该坐标
	  if (nx==a-1 && ny==b-1 && nz==c-1)
	  {
		  return tmp.t;        //若是终点,返回其耗时
	  }
	}
  }
  return -1;              //所有状态都被查找完,仍得不到所需坐标,返回-1
}

int main()
{
	int T,i,j,k;
	scanf("%d",&T);
	while (T--)
	{
		int a,b,c,t;
		scanf("%d%d%d%d",&a,&b,&c,&t);
		for(i=0;i<a;i++)                   //初始化
		{	for (j=0;j<b;j++)
			{
               for (k=0;k<c;k++)
			   {
				   scanf("%d",&maze[i][j][k]);//输入立方体信息
				   mark[i][j][k]=false;       //初始化标记数组  
			   }
			}
		}
		while (Q.empty()==false)
		{
			Q.pop();                       //清空队列,防止上组数据遗留                 
		}
        mark[0][0][0]=true;          //标记起点
		N tmp;
		tmp.t=tmp.x=tmp.y=tmp.z=0;   //初始状态
		Q.push(tmp);                 
		int rec=BFS(a,b,c);          //广度优先搜索
		if (rec<=t)
		{
			printf("%d\n",rec);
		}
		else
		{
			printf("-1\n");
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值