华为非AI方向笔试真题 - 楼内救人

楼内救人(Py/Java/C++/Js/Go)题解

华为笔试真题 6月12号 非AI方向 第三题 300分题型

题目内容

你是一名游戏开发工程师,正在设计一款楼内救人的小游戏。游戏地图是一个 m×n×2m \times n \times 2m×n×2 的 2 层楼地图,每个格子代表一个区域:

  • 0:空地(可以通行)
  • 1:墙壁(不可通行)
  • 2:起点(有且只有1个,在任意一层)
  • 3:终点(有且只有1个,在任意一层,可能与起点在同一层)
  • 4:楼梯(每层楼有且只有1个)
    玩家从起点出发,每次只能上下左右移动一格,不能穿过墙壁。目标是找到从起点到终点救人的最短路径(以步数计),并返回路径长度。
    注意:
  1. 通过楼梯算 1 步,除了通过楼梯外,无法跨楼层移动。
  2. 如果无法到达终点救人,返回 -1。
  3. 起点、终点、楼梯所在位置不重叠。

输入描述

第 1 行输入 mmm nnn(2≤m,n≤2562 \leq m, n \leq 2562≤m,n≤256)

接下来的第 2 ~ m+1m+1m+1 行,每行有 nnn 个整数 xxx 代表第 1 层地图

第 m+2m+2m+2 ~ 2∗m+12*m+12∗m+1 行,每行有 nnn 个整数 xxx 代表第 2 层地图

输出描述

返回路径长度,如无法到达终点救人,返回 -1

样例1

输入

复制代码
3 3
2 0 1
0 1 4
0 0 0
0 4 0
1 0 1
1 0 3

输出

复制代码
9

说明

从第一层的 (0,0) 出发,经过 (0,1) -> (0,2) -> (1,2) -> (2,2) -> (2,1) 到楼梯 5 步,上楼 1 步,第二层的 (1,0) -> (1,1) -> (1,2) -> (2,2) 到目标 3 步,共 9 步。

样例2

输入

复制代码
2 2
2 0
4 1
4 1
1 3

输出

复制代码
-1

说明

题解

思路

BFS算法

  1. 这题相比常规的二维BFS差异是增加了到两个地图以及图之间通过楼梯进行移动。
  2. 对于差异的处理通过以下以下方式实现
    1. 将地图通过三维进行组织
    2. 地图一层和二层只能通过楼梯位置进行跨越
  3. 预处理:接收输入地图通过三维数组进行存储,记录起点位置、终点位置和每一层楼梯位置。
  4. 然后从起点进行BFS扩散,使用队列进行模拟,队列中存储{当前层,横坐标,纵坐标}结构,不是楼梯位置正常执行上下左右移动,对于楼梯位置额外增加进行层级跨越处理即可,记录每个位置到起点的最小距离。
  5. 终点位置不可达输出-1,否则输出对应距离即可。

C++

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

struct node {
    int x;
    int y;
    int c;

    node(int x, int y, int c)
        : x(x), y(y), c(c) {}

    node() = default;

    bool operator==(const node& other) const {
        return x == other.x
            && y == other.y
            && c == other.c;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int m , n;
    cin >> m >> n;
    node start, end;
    vector<node> stairs;
    vector<vector<vector<int>> > grid(2, vector<vector<int>>(m, vector<int>(n)));
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < m; j++) {
            for (int k = 0; k < n; k++) {
                int x;
                cin >> x;
                grid[i][j][k] = x;
                if (x == 2) {
                    start = {j, k, i};
                } else if (x == 3) {
                    end = {j, k, i};
                } else if (x == 4) {
                    stairs.push_back({j, k, i});
                }
            }
        }
    }
    
    vector<vector<vector<int>> > dist(2, vector<vector<int>>(m, vector<int>(n, INT_MAX)));
    queue<node> q;
    q.push(start);
    dist[start.c][start.x][start.y] = 0;
    int dx[4] = {1,-1,0,0};
    int dy[4] = {0,0,1,-1};
    while (!q.empty()) {
        node cur = q.front();
        q.pop();
        if (cur == end) {
            break;
        }
        int x = cur.x;
        int y = cur.y;
        int c = cur.c;
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            // 超过边界
            if (nx < 0 || nx >= m || ny < 0 || ny >= n) {
                continue;
            }
            // 以访问或者为墙壁
            if (dist[c][nx][ny] != INT_MAX || grid[c][nx][ny] == 1) {
                continue;
            }
            dist[c][nx][ny] = dist[c][x][y] + 1;
            q.push({nx, ny, c});
        } 
        // 额外加入处理上楼
        if (cur == stairs[c]) {
            int nc = c ^ 1;
            node ns = stairs[c ^ 1];
            int nx = ns.x;
            int ny = ns.y;
            if (dist[nc][nx][ny] == INT_MAX) {
                dist[nc][nx][ny] = dist[c][x][y] + 1;
                q.push({nx, ny, nc});
            }
        }
    }
    int ans = dist[end.c][end.x][end.y] == INT_MAX ? -1 : dist[end.c][end.x][end.y];
    cout << ans;
    return 0;
}    

java

java 复制代码
import java.io.*;
import java.util.*;

public class Main {

    static class Node {
        int x;
        int y;
        int c;

        Node(int x, int y, int c) {
            this.x = x;
            this.y = y;
            this.c = c;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (!(obj instanceof Node)) return false;
            Node other = (Node) obj;
            return x == other.x && y == other.y && c == other.c;
        }
    }

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String[] first = br.readLine().split(" ");
        int m = Integer.parseInt(first[0]);
        int n = Integer.parseInt(first[1]);

        Node start = null;
        Node end = null;

        List<Node> stairs = new ArrayList<>();

        int[][][] grid = new int[2][m][n];

        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < m; j++) {
                String[] arr = br.readLine().split(" ");

                for (int k = 0; k < n; k++) {
                    int x = Integer.parseInt(arr[k]);
                    grid[i][j][k] = x;

                    if (x == 2) {
                        start = new Node(j, k, i);
                    } else if (x == 3) {
                        end = new Node(j, k, i);
                    } else if (x == 4) {
                        stairs.add(new Node(j, k, i));
                    }
                }
            }
        }

        int[][][] dist = new int[2][m][n];

        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < m; j++) {
                Arrays.fill(dist[i][j], Integer.MAX_VALUE);
            }
        }

        Queue<Node> q = new LinkedList<>();
        q.offer(start);

        dist[start.c][start.x][start.y] = 0;

        int[] dx = {1, -1, 0, 0};
        int[] dy = {0, 0, 1, -1};

        while (!q.isEmpty()) {
            Node cur = q.poll();

            if (cur.equals(end)) {
                break;
            }

            int x = cur.x;
            int y = cur.y;
            int c = cur.c;

            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];

                // 超过边界
                if (nx < 0 || nx >= m || ny < 0 || ny >= n) {
                    continue;
                }

                // 已访问或者为墙壁
                if (dist[c][nx][ny] != Integer.MAX_VALUE || grid[c][nx][ny] == 1) {
                    continue;
                }

                dist[c][nx][ny] = dist[c][x][y] + 1;
                q.offer(new Node(nx, ny, c));
            }

            // 额外加入处理上楼
            if (cur.equals(stairs.get(c))) {
                int nc = c ^ 1;

                Node ns = stairs.get(c ^ 1);

                int nx = ns.x;
                int ny = ns.y;

                if (dist[nc][nx][ny] == Integer.MAX_VALUE) {
                    dist[nc][nx][ny] = dist[c][x][y] + 1;
                    q.offer(new Node(nx, ny, nc));
                }
            }
        }

        int ans = dist[end.c][end.x][end.y] == Integer.MAX_VALUE
                ? -1
                : dist[end.c][end.x][end.y];

        System.out.println(ans);
    }
}

python

python 复制代码
from collections import deque
import sys


class Node:
    def __init__(self, x, y, c):
        self.x = x
        self.y = y
        self.c = c

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y and self.c == other.c


data = sys.stdin.read().strip().splitlines()

m, n = map(int, data[0].split())

start = None
end = None
stairs = []

grid = [[[0] * n for _ in range(m)] for _ in range(2)]

idx = 1

for i in range(2):
    for j in range(m):
        row = list(map(int, data[idx].split()))
        idx += 1

        for k in range(n):
            x = row[k]
            grid[i][j][k] = x

            if x == 2:
                start = Node(j, k, i)
            elif x == 3:
                end = Node(j, k, i)
            elif x == 4:
                stairs.append(Node(j, k, i))

dist = [[[float("inf")] * n for _ in range(m)] for _ in range(2)]

q = deque()
q.append(start)

dist[start.c][start.x][start.y] = 0

dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]

while q:
    cur = q.popleft()

    if cur == end:
        break

    x = cur.x
    y = cur.y
    c = cur.c

    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]

        # 超过边界
        if nx < 0 or nx >= m or ny < 0 or ny >= n:
            continue

        # 已访问或者为墙壁
        if dist[c][nx][ny] != float("inf") or grid[c][nx][ny] == 1:
            continue

        dist[c][nx][ny] = dist[c][x][y] + 1
        q.append(Node(nx, ny, c))

    # 额外加入处理上楼
    if cur == stairs[c]:
        nc = c ^ 1

        ns = stairs[c ^ 1]

        nx = ns.x
        ny = ns.y

        if dist[nc][nx][ny] == float("inf"):
            dist[nc][nx][ny] = dist[c][x][y] + 1
            q.append(Node(nx, ny, nc))

ans = dist[end.c][end.x][end.y]

print(-1 if ans == float("inf") else int(ans))

javascript

js 复制代码
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const lines = [];

rl.on('line', line => {
    lines.push(line);
});

rl.on('close', () => {

    class Node {
        constructor(x, y, c) {
            this.x = x;
            this.y = y;
            this.c = c;
        }

        equals(other) {
            return this.x === other.x &&
                   this.y === other.y &&
                   this.c === other.c;
        }
    }

    let idx = 0;

    const [m, n] = lines[idx++].trim().split(/\s+/).map(Number);

    let start = null;
    let end = null;

    const stairs = [];

    const grid = Array.from(
        { length: 2 },
        () => Array.from(
            { length: m },
            () => Array(n).fill(0)
        )
    );

    for (let i = 0; i < 2; i++) {
        for (let j = 0; j < m; j++) {
            const row = lines[idx++].trim().split(/\s+/).map(Number);

            for (let k = 0; k < n; k++) {
                const x = row[k];

                grid[i][j][k] = x;

                if (x === 2) {
                    start = new Node(j, k, i);
                } else if (x === 3) {
                    end = new Node(j, k, i);
                } else if (x === 4) {
                    stairs.push(new Node(j, k, i));
                }
            }
        }
    }

    const INF = Number.MAX_SAFE_INTEGER;

    const dist = Array.from(
        { length: 2 },
        () => Array.from(
            { length: m },
            () => Array(n).fill(INF)
        )
    );

    const q = [];

    q.push(start);

    dist[start.c][start.x][start.y] = 0;

    const dx = [1, -1, 0, 0];
    const dy = [0, 0, 1, -1];

    let head = 0;

    while (head < q.length) {

        const cur = q[head++];

        if (cur.equals(end)) {
            break;
        }

        const x = cur.x;
        const y = cur.y;
        const c = cur.c;

        for (let i = 0; i < 4; i++) {
            const nx = x + dx[i];
            const ny = y + dy[i];

            // 超过边界
            if (nx < 0 || nx >= m || ny < 0 || ny >= n) {
                continue;
            }

            // 已访问或者为墙壁
            if (dist[c][nx][ny] !== INF || grid[c][nx][ny] === 1) {
                continue;
            }

            dist[c][nx][ny] = dist[c][x][y] + 1;
            q.push(new Node(nx, ny, c));
        }

        // 额外加入处理上楼
        if (cur.equals(stairs[c])) {

            const nc = c ^ 1;

            const ns = stairs[c ^ 1];

            const nx = ns.x;
            const ny = ns.y;

            if (dist[nc][nx][ny] === INF) {
                dist[nc][nx][ny] = dist[c][x][y] + 1;
                q.push(new Node(nx, ny, nc));
            }
        }
    }

    const ans = dist[end.c][end.x][end.y];

    console.log(ans === INF ? -1 : ans);
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

type Node struct {
	x int
	y int
	c int
}

func (a Node) Equal(b Node) bool {
	return a.x == b.x &&
		a.y == b.y &&
		a.c == b.c
}

func main() {
	in := bufio.NewReader(os.Stdin)

	var m, n int
	fmt.Fscan(in, &m, &n)

	var start Node
	var end Node

	stairs := make([]Node, 0)

	grid := make([][][]int, 2)

	for i := 0; i < 2; i++ {
		grid[i] = make([][]int, m)

		for j := 0; j < m; j++ {
			grid[i][j] = make([]int, n)

			for k := 0; k < n; k++ {
				var x int
				fmt.Fscan(in, &x)

				grid[i][j][k] = x

				if x == 2 {
					start = Node{j, k, i}
				} else if x == 3 {
					end = Node{j, k, i}
				} else if x == 4 {
					stairs = append(stairs, Node{j, k, i})
				}
			}
		}
	}

	INF := math.MaxInt32

	dist := make([][][]int, 2)

	for i := 0; i < 2; i++ {
		dist[i] = make([][]int, m)

		for j := 0; j < m; j++ {
			dist[i][j] = make([]int, n)

			for k := 0; k < n; k++ {
				dist[i][j][k] = INF
			}
		}
	}

	q := make([]Node, 0)
	q = append(q, start)

	dist[start.c][start.x][start.y] = 0

	dx := []int{1, -1, 0, 0}
	dy := []int{0, 0, 1, -1}

	head := 0

	for head < len(q) {

		cur := q[head]
		head++

		if cur.Equal(end) {
			break
		}

		x := cur.x
		y := cur.y
		c := cur.c

		for i := 0; i < 4; i++ {
			nx := x + dx[i]
			ny := y + dy[i]

			// 超过边界
			if nx < 0 || nx >= m || ny < 0 || ny >= n {
				continue
			}

			// 已访问或者为墙壁
			if dist[c][nx][ny] != INF || grid[c][nx][ny] == 1 {
				continue
			}

			dist[c][nx][ny] = dist[c][x][y] + 1
			q = append(q, Node{nx, ny, c})
		}

		// 额外加入处理上楼
		if cur.Equal(stairs[c]) {

			nc := c ^ 1

			ns := stairs[c^1]

			nx := ns.x
			ny := ns.y

			if dist[nc][nx][ny] == INF {
				dist[nc][nx][ny] = dist[c][x][y] + 1
				q = append(q, Node{nx, ny, nc})
			}
		}
	}

	ans := dist[end.c][end.x][end.y]

	if ans == INF {
		fmt.Println(-1)
	} else {
		fmt.Println(ans)
	}
}
相关推荐
金启攻1 小时前
【鸿蒙原生应用开发实战】第三篇:列表页与标签筛选功能 — 打造高效的天体列表
华为·harmonyos
一切皆是因缘际会1 小时前
隐层表征解构:LLM感知式幻觉稀疏成因
算法·数学建模·ai·架构
Irissgwe1 小时前
二叉树进阶
数据结构·c++·算法·c·二叉搜索树
无限码力1 小时前
华为非AI方向笔试真题 - 容器镜像平均大小统计
算法·华为·华为非ai方向笔试真题·华为笔试真题·华为非ai笔试真题·华为0612非ai笔试真题
Keep_Trying_Go1 小时前
华为开源框架MindSpore基本使用
华为·开源
无限码力1 小时前
华为非AI方向0612笔试真题-循环异或加密器(详细思路+多语言题解)
算法·华为·华为非ai方向笔试真题·华为笔试真题·华为0612笔试真题
凌波粒1 小时前
LeetCode--1584. 连接所有点的最小费用(最小生成树/Prim算法/Kruskal算法)
算法·leetcode·职场和发展
simidagogogo1 小时前
生产环境推荐系统最隐蔽的坑:Training-Serving Skew 详解与实战
算法·spark·推荐算法
烛衔溟1 小时前
HarmonyOS 工程目录、配置文件与 Stage 模型核心
华为·harmonyos