HDU1253 胜利大逃亡
题意:
在一个三维的房间里找到距离出口的最短路径,比较最短路径花的时间和魔王回来的时间 T,若小于等于T,则出逃成功。起点坐标为(0,0,0),终点坐标为(a-1, b-1, c-1),地图中0为通路,1为墙。
思路:
典型的BFS,记录的数组从常见的二维扩充到了三维。依然使用队列维护,把初始状态加入队列,修改dis[][][]数组的值,取出队首元素,让元素依次出队,判断是否到达终点,若还没到达,向邻近的六个方向移动,判断移动后的点是否越界、该点是否可达、该点是否被访问等条件,若满足,则将改点加入队列,继续判断。直到队列为空或到达终点,搜索结束。
http://acm.hdu.edu.cn/showproblem.php?pid=1253
#include<cstdio>
#include<queue>
#define INF 100000000
#define MAX 50
using namespace std;
struct P{
int x, y, z;
P(int a, int b, int c){
x = a;
y = b;
z = c;
}
};
int a, b, c, t;
int dis[MAX][MAX][MAX];
int maze[MAX][MAX + 1][MAX + 1];
int dir[6][3]={{1,0,0},{-1,0,0},{0,0,1},{0,0,-1},{0,1,0},{0,-1,0}};
int bfs(){
queue<P> que;
que.push(P(0, 0, 0));
dis[0][0][0] = 0;
while(!que.empty()){
P p = que.front();
que.pop();
if(p.x == a - 1 && p.y == b - 1 && p.z == c - 1)
break;
for(int i = 0;i < 6;i++){
int nx = p.x + dir[i][0], ny = p.y + dir[i][1], nz = p.z + dir[i][2];
if(nx >= 0 && nx < a && ny >= 0 && ny < b && nz >= 0 && nz < c && maze[nx][ny][nz] != 1 && dis[nx][ny][nz] == INF){
que.push(P(nx, ny, nz));
dis[nx][ny][nz] = dis[p.x][p.y][p.z] + 1;
}
}
}
return dis[a - 1][b - 1][c - 1];
}
main(){
int n;
scanf("%d", &n);
while(n--){
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]);
}
}
}
for(int i = 0;i < a;i++){
for(int j = 0;j < b;j++){
for(int k = 0;k < c;k++){
dis[i][j][k] = INF;
}
}
}
int res = bfs();
if(res <= t)
printf("%d\n", res);
else
printf("-1\n");
}
}
总结:
做了一些BFS的题,发现除了用队列来维护,将初始状态入队等固定格式外,最重要的是根据不同题目状态记录的方式不同。有的题目是二维数组,有的是三维,判断新的点是否加入队列的条件也略有不同,只要做题的时候仔细判断好状态转移的条件,不要漏,一般就能把题目做出来。