题解 | #Jelly#
Jelly
https://ac.nowcoder.com/acm/problem/201613
链接:https://ac.nowcoder.com/acm/problem/201613
来源:牛客网
思路:答案等同于求迷宫中最短路径步数,所以用bfs,这题无非是把二维给换成了三维,但是做法和二维一样,也是一道基础的模板题
来源:牛客网
题目描述
Nancy喜欢吃果冻!
下面给出果冻的情况,请你帮忙计算一下她能吃多少块果冻叭!
Nancy钻进了一个n×n×nn \times n \times nn×n×n的果冻里,她想从(1,1,1)一路上、下、左、右、前、后六个方向吃到(n,n,n)。
但果冻毕竟是有许多口味的,标记为*的口味是Nancy不愿意吃的,其余的果冻均标记为.。
Nancy不想吃坏肚子,于是她想尽可能少的吃果冻。下面给出果冻的情况,请你帮忙计算一下她能吃多少块果冻叭!
输入描述:
第一行:一个整数n。
接下来n层,每组n行,每行n列,表示果冻(i,j,k)的情况(如题目描述所述)。
数据满足:1≤n≤1001 \leq n \leq 1001≤n≤100,保证果冻(1,1,1)不是Nancy不愿意吃的。
输出描述:
如果可以到达(n,n,n),请输出路上吃的果冻数量,否则请输出-1。
直接用bfs模板做就好啦
bfs模板,来自 <https://www.luogu.com.cn/article/z35v1xn7>,非常简洁且好用!
queue<node> q;
void bfs(){
while(!q.empty()) {
node temp=q.front();
q.pop();
if(完成目标) {
记录;
return;
}
for(int i=0;i<m;i++)//m为方向数组长度
{
int xx=temp.x+dx[i];
int yy=temp.y+dy[i];
if(下标越界||已被标记) {
continue;
}
mark[xx][yy]=1;
q.push(node{xx,yy});//注意,node{xx,yy}这种形式只适用于C++20及以上版本
}
}
}
void bfs(){
while(!q.empty()) {
node temp=q.front();
q.pop();
if(完成目标) {
记录;
return;
}
for(int i=0;i<m;i++)//m为方向数组长度
{
int xx=temp.x+dx[i];
int yy=temp.y+dy[i];
if(下标越界||已被标记) {
continue;
}
mark[xx][yy]=1;
q.push(node{xx,yy});//注意,node{xx,yy}这种形式只适用于C++20及以上版本
}
}
}
代码如下:
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
char s[120][120][120]; //存储图数组
int vis[120][120][120]; //存储状态数组
int dir[6][3]= {{1,0,0},{-1,0,0},{0,1,0},{0,0,1},{0,-1,0},{0,0,-1}}; //方向数组
int ans=-1,n;
struct node {
int num,z,x,y;
};
queue<node>q; //STL的队列
void BFS() {
while(!q.empty()) { //队列为空时退出循环
node temp=q.front(); //取队列的第一个值
q.pop();
if(temp.x==n-1 && temp.y==n-1 && temp.z==n-1) { //如果队列中的x,y,z都到了终点,则获取其步数值
ans=temp.num;
return;
}
for(int i=0; i<6; i++) { //6个方向依次探索
int zz=temp.z+dir[i][0];
int xx=temp.x+dir[i][1];
int yy=temp.y+dir[i][2];
if(vis[zz][xx][yy] || xx<0 || yy<0 || zz<0 || xx>=n || yy>=n || zz>=n || s[zz][xx][yy]=='*') { //如果无法到达此处,则continue
continue;
}
vis[zz][xx][yy]=1; //更新此处状态
q.push(node {temp.num+1,zz,xx,yy}); //将此坐标存入队列
}
}
}
int main() {
scanf("%d",&n);
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
scanf("%s",s[i][j]);
}
}
vis[0][0][0]=1; //更新起点状态
q.push(node {1,0,0,0}); //记得把起点存入队列里再bfs,不然bfs没用
BFS();
printf("%d\n",ans);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
char s[120][120][120]; //存储图数组
int vis[120][120][120]; //存储状态数组
int dir[6][3]= {{1,0,0},{-1,0,0},{0,1,0},{0,0,1},{0,-1,0},{0,0,-1}}; //方向数组
int ans=-1,n;
struct node {
int num,z,x,y;
};
queue<node>q; //STL的队列
void BFS() {
while(!q.empty()) { //队列为空时退出循环
node temp=q.front(); //取队列的第一个值
q.pop();
if(temp.x==n-1 && temp.y==n-1 && temp.z==n-1) { //如果队列中的x,y,z都到了终点,则获取其步数值
ans=temp.num;
return;
}
for(int i=0; i<6; i++) { //6个方向依次探索
int zz=temp.z+dir[i][0];
int xx=temp.x+dir[i][1];
int yy=temp.y+dir[i][2];
if(vis[zz][xx][yy] || xx<0 || yy<0 || zz<0 || xx>=n || yy>=n || zz>=n || s[zz][xx][yy]=='*') { //如果无法到达此处,则continue
continue;
}
vis[zz][xx][yy]=1; //更新此处状态
q.push(node {temp.num+1,zz,xx,yy}); //将此坐标存入队列
}
}
}
int main() {
scanf("%d",&n);
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
scanf("%s",s[i][j]);
}
}
vis[0][0][0]=1; //更新起点状态
q.push(node {1,0,0,0}); //记得把起点存入队列里再bfs,不然bfs没用
BFS();
printf("%d\n",ans);
return 0;
}
算法入门班习题题解&感悟 文章被收录于专栏
这是本人对于算法入门班共十三章习题的题解与个人的一些感悟,本人写题解的目的是对于某些经典的/陌生的/无从下手的/思维方向错误的题目加深印象。 希望自己能够在学习算法的路上走得更远,今天也是努力学习的一天!