题目
题目描述:Nancy喜欢吃果冻!
Nancy钻进了一个n×n×n的果冻里,她想从(1,1,1)一路上、下、左、右、前、后六个方向吃到(n,n,n)。
但果冻毕竟是有许多口味的,标记为*的口味是Nancy不愿意吃的,其余的果冻均标记为.。
Nancy不想吃坏肚子,于是她想尽可能少的吃果冻。
下面给出果冻的情况,请你帮忙计算一下她能吃多少块果冻叭!
输入描述:
第一行:一个整数n。接下来n层,每组n行,每行n列,表示果冻(i,j,k)的情况(如题目描述所述)。
数据满足:1≤n≤100,保证果冻(1,1,1)不是Nancy不愿意吃的。
输出描述:
如果可以到达(n,n,n),请输出路上吃的果冻数量,否则请输出-1。
解析
题就是简单的bfs
操作操作:
- 三维数组作为地图(mp数组)保存题目信息,建立一个已访问数组(visited数组)保存节点的访问信息,保证每个节点不被重复访问。
- 用队列对地图进行遍历。先将起点进队,然后访问起点可以到达的所有节点(地图外和禁止区域当然就不让访问了)
- 然后依次类推,每次将队首节点拿出来访问,直到访问到终点。
- 因为我们队列保存的是结构体,每个节点自带步数。(步数自然等于访问他的节点+1)所以输出该节点的步数就好了。
代码
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define js ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int MAX = 1e2 + 7;
//代码预处理
int walk[6][3] = { {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1} };//三轴移动
int visited[MAX][MAX][MAX], mp[MAX][MAX][MAX], n;//已访问数组,地图,大小
typedef struct {
int x, y, z, eat;//坐标与吃的数量
} Node;
int judge(Node next);//判断接下来访问的节点是否是合法位置(墙或者不能走的格子)
int dfs();//广度优先遍历
int main() {
js;
cin >> n;
memset(mp, -1, sizeof(mp));
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
char ch; cin >> ch;
if (ch == '.') mp[i][j][k] = 0;
}
//初始化地图数组
cout << dfs() << endl;
return 0;
}
int judge(Node next) {
if (mp[next.x][next.y][next.z]) return 0;//判墙或者不能走的节点
if (visited[next.x][next.y][next.z]) return 0;//判是否走过
return 1;
}
int dfs() {
memset(visited, 0, sizeof(visited));
visited[1][1][1] = 1;
Node top; top.x = 1; top.y = 1; top.z = 1; top.eat = 1;
queue<Node> que; que.push(top);
//队列与访问数组初始化
while (!que.empty()) {
top = que.front(); que.pop();
if (top.x == n && top.y == n && top.z == n) return top.eat;
//抵达终点则有数量返回,否则最后会全部出队返回-1
for (int i = 0; i < 6; i++) {
Node next;
next.x = top.x + walk[i][0];
next.y = top.y + walk[i][1];
next.z = top.z + walk[i][2];
next.eat = top.eat + 1;
//得到下一个节点
if (judge(next)) {
que.push(next);
visited[next.x][next.y][next.z] = 1;
}
//可走则进队
}
}
return -1;
} 
京公网安备 11010502036488号