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
思路:以前做的地图都是二维的,这是我的第一个三维的地图,刚开始没想到怎么定义方向合适,但还是想到方法了。
方向可以这样定义:dir[6][3]={{0,1,0},{0,-1,0},{0,0,1},{0,0,-1},{1,0,0},{-1,0,0}}; 用二维数组,简单粗暴。
方法和一般的广搜一样,看代码:
#include<cstring> #include<iostream> #include<cmath> #include<queue> using namespace std; int dir[6][3]={{0,1,0},{0,-1,0},{0,0,1},{0,0,-1},{1,0,0},{-1,0,0}};/*这里用二维数组表示更方便些*/ int map[51][51][51]; bool vis[51][51][51];//标记数组 int x,y,z; struct node{ int x; int y; int z; int steps; }; bool isGo(int a, int b, int c){//判断当前路径是否可走 if(a>=0 && a<=x-1 &&b>=0 &&b<=y-1 &&c>=0 &&c<=z-1&& map[a][b][c]==0) return true;//没越界而且当前点有路可走 return false; } int bfs(int steps){ node st,ed; queue<node> q; st.x=0; st.y=0; st.z=0; st.steps=0; q.push(st); memset(vis,false,sizeof(vis)); vis[st.x][st.y][st.z]=true; while(!q.empty()){ st=q.front(); q.pop(); if(st.steps>steps) return -1; if(st.x == x-1 &&st.y == y-1 &&st.z == z-1 &&st.steps<=steps) return st.steps; for(int i=0; i<6; ++i){ ed.x=st.x+dir[i][0]; ed.y=st.y+dir[i][1]; ed.z=st.z+dir[i][2]; if(isGo(ed.x, ed.y, ed.z) && !vis[ed.x][ed.y][ed.z]){ vis[ed.x][ed.y][ed.z]=true; ed.steps=st.steps+1; if(abs(ed.x-x+1)+abs(ed.y-y+1)+abs(ed.z-z+1)+ed.steps>steps) continue;//判断当前路径时候最终可以到达终点,剪枝 q.push(ed); } } } return -1;//所有点都走过但没能到达 } int main(){ int t; scanf("%d",&t); while(t--){ int steps; scanf("%d%d%d%d", &x, &y, &z, &steps); for(int i=0; i<x; ++i){ for(int j=0; j<y; ++j){ for(int k=0; k<z; ++k) scanf("%d", &map[i][j][k]); } } int ans=bfs(steps); printf("%d\n", ans); } return 0; }