华为23年笔试题

消息传输

题目描述

在给定的 m x n (1 <= m, n <= 1000) 网格地图 grid 中,分布着一些信号塔,用于区域间通信。

每个单元格可以有以下三种状态:

值 0 代表空地,无法传递信号;

值 1 代表信号塔 A,在收到消息后,信号塔 A 可以在 1ms 后将信号发送给上下左右四个方向的信号塔;

值 2 代表信号塔 B,在收到消息后,信号塔 B 可以在 2ms 后将信号发送给上下左右四个方向的信号塔。

给定一个坐标 (j, k),输入保证坐标 (j, k) 位置一定有信号塔。在坐标 (j, k) 位置的信号塔触发一个信号。

要求返回网格地图中所有信号塔收到信号的最短时间,单位为 ms。如果有信号塔无法收到信号,则返回 -1。

输入描述

第一行:网格的列数 n。

第二行:网格的行数 m。

第三行:触发信号的信号塔坐标 (j, k)。

接下来的 m 行:每行包含 n 个整数,表示该行网格中每个位置的信号塔安装信息(通过空格间隔每个状态值)。

输出描述

输出返回 网格地图中所有信号塔收到信号的最小时间,单位为ms。如果不可能,返回-1。

输入示例
3
3
1 0
0 1 2
1 2 1
0 1 2
输出示例
4

思路:

本题我使用的是bfs,time[][]记录每个位置消息到达时间,当前结点的周围基站的旧的消息 到达时间大于使用当前结点传播的新的消息到达时间时或者周围基站还没被传播 过消息就把这些满足要求的基站加入到队列 ,并更新这些基站的传播时间,借此题复习bfs

bfs模板:

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 表示四个方向
// grid 是地图,也就是一个二维数组
// visited标记访问过的节点,不要重复访问
// x,y 表示开始搜索节点的下标
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {
    queue<pair<int, int>> que; // 定义队列
    que.push({x, y}); // 起始节点加入队列
    visited[x][y] = true; // 只要加入队列,立刻标记为访问过的节点
    while(!que.empty()) { // 开始遍历队列里的元素
        pair<int ,int> cur = que.front(); que.pop(); // 从队列取元素
        int curx = cur.first;
        int cury = cur.second; // 当前节点坐标
        for (int i = 0; i < 4; i++) { // 开始想当前节点的四个方向左右上下去遍历
            int nextx = curx + dir[i][0];
            int nexty = cury + dir[i][1]; // 获取周边四个方向的坐标
            if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 坐标越界了,直接跳过
            if (!visited[nextx][nexty]) { // 如果节点没被访问过
                que.push({nextx, nexty});  // 队列添加该节点为下一轮要遍历的节点
                visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问
            }
        }
    }

}

当前题目代码:

import java.util.*;

class Main {
    static int[][] go = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();//列数
        int m = in.nextInt();//行数
    
        int[][] map = new int[m][n];//记录基站位置关系
        int  [][] time = new int[m][n];//-1:没访问 记录到每个结点的最短时间
       for(int i=0;i<time.length;i++){
    Arrays.fill(time[i],-1);
}
        //起始信号塔的横纵坐标
        int x = in.nextInt();
        int y = in.nextInt();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int c = in.nextInt();
                map[i][j] = c;
            }
        }

        int s = bfs(map, time, x, y);
        System.out.println(s);
    }

    static int bfs(int[][] map, int[][] time, int x, int y) {
        int max_time = 0;//记录时间
        List<int[]> queue = new LinkedList<>();//定义队列记录坐标
        queue.add(new int[]{x, y});//起始结点加入队列
        time[x][y] = 0;       // 只要加入队列,立刻标记为访问过的节点
        while (!queue.isEmpty()) { // 开始遍历队列里的元素
          //从队列取出元素
            int[] ints =  queue.remove(0);
            int curx = ints[0];
            int cury = ints[1]; //获得当前位置的坐标
            //查询当前基站的传播效率
          int delay= map[curx][cury];
            // 开始向当前节点的四个方向左右上下去遍历
            for (int i = 0; i < go.length; i++) {
                //获得周围结点
                int nextX = curx + go[i][0];
                int nexty = cury + go[i][1];
               // 如果相邻信号塔尚未接收到信号||或者他们应该更早接收到,更新它们的接收时间(当前信号塔的接收时间 + 相邻信号塔的传播延迟),并将它们加入队列。
                if (nextX < 0 || nextX >= map.length || nexty < 0 || nexty >= map[0].length || map[nextX][nexty] == 0) {
                    continue;
                }
                //周围结点的时间
                   int newtime=delay+time[curx][cury];
                if(time[nextX][nexty]==-1||newtime<time[nextX][nexty]){
                    time[nextX][nexty]=newtime;
                    queue.add(new int[]{nextX,nexty});
            
                }

            }

        }
        //bfs结束,查看有没有基站没被访问
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                if(map[i][j]>0&&time[i][j]==-1){
                    return -1;
                }
                max_time=Integer.max(max_time,time[i][j]);
            }
        }
      return max_time;
    }


}
相关推荐
青椒大仙KI111 分钟前
24/9/19 算法笔记 kaggle BankChurn数据分类
笔记·算法·分类
^^为欢几何^^5 分钟前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
豆浩宇5 分钟前
Halcon OCR检测 免训练版
c++·人工智能·opencv·算法·计算机视觉·ocr
浅念同学21 分钟前
算法.图论-并查集上
java·算法·图论
何不遗憾呢29 分钟前
每日刷题(算法)
算法
立志成为coding大牛的菜鸟.34 分钟前
力扣1143-最长公共子序列(Java详细题解)
java·算法·leetcode
鱼跃鹰飞34 分钟前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先
liangbm340 分钟前
数学建模笔记——动态规划
笔记·python·算法·数学建模·动态规划·背包问题·优化问题
潮汐退涨月冷风霜1 小时前
机器学习之非监督学习(四)K-means 聚类算法
学习·算法·机器学习
B站计算机毕业设计超人1 小时前
计算机毕业设计Python+Flask微博情感分析 微博舆情预测 微博爬虫 微博大数据 舆情分析系统 大数据毕业设计 NLP文本分类 机器学习 深度学习 AI
爬虫·python·深度学习·算法·机器学习·自然语言处理·数据可视化