题目1456:胜利大逃亡
- 题目描述:
-
Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T分钟后回到城堡,Ignatius每分钟能从一个坐标走到相邻的六个坐标中的其中一个.现在给你城堡的地图,请你计算出Ignatius能否在魔王回来前离开城堡(只要走到出口就算离开城堡,如果走到出口的时候魔王刚好回来也算逃亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1.
- 输入:
-
输入数据的第一行是一个正整数K,表明测试数据的数量.每组测试数据的第一行是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的大小和魔王回来的时间.然后是A块输入数据(先是第0块,然后是第1块,第2块......),每块输入数据有B行,每行有C个正整数,代表迷宫的布局,其中0代表路,1代表墙。
- 输出:
-
对于每组测试数据,如果Ignatius能够在魔王回来前离开城堡,那么请输出他最少需要多少分钟,否则输出-1.
- 样例输入:
-
1 3 3 4 20 0 1 1 1 0 0 1 1 0 1 1 1 1 1 1 1 1 0 0 1 0 1 1 1 0 0 0 0 0 1 1 0 0 1 1 0
- 样例输出:
-
11 代码如下:
#include <iostream> #include <stdio.h> #include <queue> using namespace std; /*所谓广度优先搜索,即在遍历解答树时使每次状态转移时扩展出尽可能多 的新状态,并且按照各个状态出现的先后顺序依次扩展它们。但是,这样所 需查找的状态是非常多,最坏情况下,因为每个结点都能扩展出6个新结点, 那么仅走10步,其状态数就会达到6^10,需要大量的时间才能依次遍历完这 些状态,所以我们必须采用相应的措施来制约状态的无限扩展,这个方法就 是剪枝*/ /*在起点走向终点的最短路径上,到达任意一个中间结点所用的时间都是起 点到达这个结点的最短时间,那么我们所要查找的答案比不可能由该状态进 行若干次扩展后得到*/ /*例如:当我们第一次查找到包含点(x,y,z)的坐标状态后,其后查找到的 任意包含该坐标的状态都不必扩展*/ bool mark[50][50][50]; //标记数组 int maze[50][50][50]; //保存立方体信息 struct N{ int x; int y; int z; int t; }; queue<N> Q; //队列,队列中的元素为状态 int go[][3]={ //坐标变换数组,由坐标(x,y,z)扩展得到的新坐标均可 {1,0,0}, //通过(x+go[i][0],y+go[i][1],z+go[i][2])得到 {-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 temp; //新的状态 temp.x=nx; temp.y=ny; temp.z=nz; //新状态包含的坐标 temp.t=now.t+1; //新状态的耗时 Q.push(temp); //将新状态加入到队列 mark[nx][ny][nz]=true; //标记该坐标 if(nx==a-1&&ny==b-1&&nz==c-1) return temp.t; } } return -1; } int main(){ int T; scanf("%d",&T); while(T--){ int a,b,c,t; scanf("%d%d%d%d",&a,&b,&c,&t); //输入 for(int i=0;i<a;i++){ for(int j=0;j<b;j++){ for(int 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 temp; temp.x=temp.y=temp.z=temp.t=0; //初始状态 Q.push(temp); //将初始状态放入队列 int rec=BFS(a,b,c); //广度优先搜索 if(rec<=t) printf("%d\n",rec); //若所需时间符合条件,则输出 else printf("-1\n"); //否则输出-1 } return 0; } /************************************************************** Problem: 1456 User: lcyvino Language: C++ Result: Accepted Time:30 ms Memory:2132 kb ****************************************************************/
时间: 2024-10-29 19:10:27