大厂秋招真题【BFS+DP】华为20230921秋招T3-PCB印刷电路板布线(留学生专场)

华为20230921秋招T3-PCB印刷电路板布线(留学生专场)

题目描述与示例

题目描述

在PCB印刷电路板设计中,器件之间的连线,要避免线路的阻抗值增大,而且器件之间还有别的器任和别的干扰源,在布线时我们希望受到的干扰尽量小。

现将电路板简化成一个M × N的矩阵,每个位置(单元格)的值表示其源干扰度。

如果单元格的值为0,表示此位置没有干扰源,如果单元格的值为非0,则表示此位置是干扰源,其值为源干扰度。连线经过干扰源或干扰源附近会增加连线的总干扰度。

位置A[x,y]的干扰源的源干扰广为d (d>0),则连线的干扰度计算如下:

1、若连线经过位置A[x,y],则其总干扰度会增加加

2、若连线经过离位置A[x,y]距离小于d的位置时,设其距离为k,则总干扰度会增加(d-k)

3、若连线经过离位置A[x,y]距离大于或等于d的位置时,总干扰都不会增加;

注:位置[x1,y1]和位置[x2,y2]之间距离的定义为:|x1-x2|+|y1-y2|

如下3x3矩阵,位置[1,1]的源干扰度是2,连线的位置序列为:[0,0]->[0,1]->[0,2]->[1,2]->[2,2]

其中[0,1][1,0]到干扰源的距离为1,会叠加1的干扰度;其他位置到[1,1]的距离均大于等于2,所以不会叠加干扰度。因此这条连线的总干扰度为2

现在我们需要将左上角的器件到右下角的器件进行连线,两个器件的位置分别是左上角的[0,0]和右下角的[M-1,N-1]。由于我们希望连线尽量地短,从位置[0,0][M-1,N-1]的连线途中,我们规定连线只能向下或向右。

请根据输入(M × N的矩阵),计算出连线的最小干扰度。

输入描述

第一行是两个整数MN(MN最大值为1000),表示行数和列数;

接着是M行的数据,每一包含N个整数,代表每个位置的源干扰度,每个源干扰度小于50

输出描述

左上角[0,0]到右下角[M-1,N-1]连线的最小总干扰度。

示例一

输入

3 3
0 0 0
0 2 0
0 0 0

输出

2

说明

其中一条可以使干扰度最小的路径为:[0,0]->[0,1]->[0,2]->[1,2]->[2,2],其干扰度为2

示例二

输入

5 5
0 0 0 0 0
0 0 2 0 0
0 2 0 2 0
0 0 0 0 0
0 0 0 0 0

输出

1

说明

先从[0,0]往下走到最下面[4,0],再往石走到右下角[4,4],途径[2,0]时叠加一个干扰度。

示例三

输入

5 5
0 0 0 0 0
0 0 2 0 0
0 2 0 2 0
0 0 2 0 0
0 0 0 0 0

输出

2

时空限制

时间限制: C/C++ 2000MS,其他语言4000MS

内存限制: C/C++ 256MB,其他语言512MB

解题思路

本题属于综合性较强的题目,结合了BFS和DP两个知识点。

首先我们需要根据原矩阵,构建出每一个位置干扰值叠加的结果,得到一个新的矩阵grid_new。这里显然就是一个基于BFS计算层数的问题。

在这里插入图片描述

在得到新的矩阵grid_new之后,问题就转变为,对grid_new构建一条从左上到右下的路径,每次只能够向右或向下移动,路径经过的点的总和需要最小。这是一个经典的路径DP问题,和LeetCode64、最小路径和完全一致。

代码

Python

# 题目:【DP】华为2023秋招-PCB印刷电路板布线
# 作者:闭着眼睛学数理化
# 算法:DP/BFS
# 代码有看不懂的地方请直接在群上提问from collections import dequeDIRECTIONS = [(0, 1), (1, 0), (0, -1), (-1, 0)]# 对于grid中每一个干扰源,以干扰源作为起点进行BFS,更新grid_new
def BFS_update_grid_new(val, grid_new, i, j, m, n):check_list = [[0] * n for _ in range(m)]check_list[i][j] = 1grid_new[i][j] += valq = deque()q.append((i, j))# 注意这里退出循环的条件和val相关while val > 1:val -= 1qSize = len(q)for _ in range(qSize):cur_x, cur_y = q.popleft()for dx, dy in DIRECTIONS:nxt_x, nxt_y = cur_x+dx, cur_y+dyif 0 <= nxt_x < m and 0 <= nxt_y < n and check_list[nxt_x][nxt_y] == 0:q.append((nxt_x, nxt_y))grid_new[nxt_x][nxt_y] += valcheck_list[nxt_x][nxt_y] = 1# 用于解决最小路径和问题的函数
def find_min_sum_path(grid_new, m, n):# 构建大小为m*n的dp数组,dp[i][j]表示# 到达grid_new中的点(i,j),所需的最小路径和dp = [[0] * (n) for _ in range(m)]# 初始化(0,0)位置dp[0][0] = grid_new[0][0]# 初始化dp数组第0行,只能从左边向右转移得到for j in range(1, n):dp[0][j] += dp[0][j-1] + grid_new[0][j]# 初始化dp数组第0列,只能从上边向下转移得到for i in range(1, m):dp[i][0] += dp[i-1][0] + grid_new[i][0]# 遍历剩余所有点# 点(i,j)的状态,只能从点(i-1,j)向下或者从点(i,j-1)向右转移得到# 故动态转移方程为dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid_new[i][j]for i in range(1, m):for j in range(1, n):dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid_new[i][j]return dp[-1][-1]# 输入行数m,列数n
m, n = map(int, input().split())
# 构建原干扰值矩阵
grid = list()
for _ in range(m):grid.append(list(map(int, input().split())))# 初始化干扰值叠加后的新矩阵gird_new
grid_new = [[0] * n for _ in range(m)]for i in range(m):for j in range(n):# 对于每一个干扰源,使用BFS更新grid_newif grid[i][j] != 0:val = grid[i][j]BFS_update_grid_new(val, grid_new, i, j, m, n)# 调用函数find_min_sum_path,输出答案
print(find_min_sum_path(grid_new, m, n))

Java

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;public class Main {private static final int[][] DIRECTIONS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};// Function to perform BFS and update gridNewprivate static void BFSUpdateGridNew(int val, int[][] gridNew, int i, int j, int m, int n) {int[][] checkList = new int[m][n];checkList[i][j] = 1;gridNew[i][j] += val;Deque<int[]> queue = new ArrayDeque<>();queue.add(new int[]{i, j});while (val > 1) {val--;int qSize = queue.size();for (int k = 0; k < qSize; k++) {int[] current = queue.poll();int curX = current[0];int curY = current[1];for (int[] dir : DIRECTIONS) {int nextX = curX + dir[0];int nextY = curY + dir[1];if (nextX >= 0 && nextX < m && nextY >= 0 && nextY < n && checkList[nextX][nextY] == 0) {queue.add(new int[]{nextX, nextY});gridNew[nextX][nextY] += val;checkList[nextX][nextY] = 1;}}}}}// Function to find the minimum sum pathprivate static int findMinSumPath(int[][] gridNew, int m, int n) {int[][] dp = new int[m][n];dp[0][0] = gridNew[0][0];for (int i = 1; i < m; i++) {dp[i][0] = dp[i - 1][0] + gridNew[i][0];}for (int j = 1; j < n; j++) {dp[0][j] = dp[0][j - 1] + gridNew[0][j];}for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + gridNew[i][j];}}return dp[m - 1][n - 1];}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();int n = sc.nextInt();int[][] grid = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {grid[i][j] = sc.nextInt();}}int[][] gridNew = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] != 0) {int val = grid[i][j];BFSUpdateGridNew(val, gridNew, i, j, m, n);}}}System.out.println(findMinSumPath(gridNew, m, n));}
}

C++

#include <iostream>
#include <vector>
#include <deque>
using namespace std;const vector<pair<int, int>> DIRECTIONS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};// Function to perform BFS and update grid_new
void BFSUpdateGridNew(int val, vector<vector<int>>& gridNew, int i, int j, int m, int n) {vector<vector<int>> checkList(m, vector<int>(n, 0));checkList[i][j] = 1;gridNew[i][j] += val;deque<pair<int, int>> q;q.push_back({i, j});while (val > 1) {val--;int qSize = q.size();for (int k = 0; k < qSize; k++) {int curX = q.front().first;int curY = q.front().second;q.pop_front();for (const auto& dir : DIRECTIONS) {int nextX = curX + dir.first;int nextY = curY + dir.second;if (nextX >= 0 && nextX < m && nextY >= 0 && nextY < n && checkList[nextX][nextY] == 0) {q.push_back({nextX, nextY});gridNew[nextX][nextY] += val;checkList[nextX][nextY] = 1;}}}}
}// Function to find the minimum sum path
int FindMinSumPath(const vector<vector<int>>& gridNew, int m, int n) {vector<vector<int>> dp(m, vector<int>(n, 0));dp[0][0] = gridNew[0][0];for (int i = 1; i < m; i++) {dp[i][0] = dp[i - 1][0] + gridNew[i][0];}for (int j = 1; j < n; j++) {dp[0][j] = dp[0][j - 1] + gridNew[0][j];}for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + gridNew[i][j];}}return dp[m - 1][n - 1];
}int main() {int m, n;cin >> m >> n;vector<vector<int>> grid(m, vector<int>(n));for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {cin >> grid[i][j];}}vector<vector<int>> gridNew(m, vector<int>(n, 0));for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] != 0) {int val = grid[i][j];BFSUpdateGridNew(val, gridNew, i, j, m, n);}}}cout << FindMinSumPath(gridNew, m, n) << endl;return 0;
}

时空复杂度

时间复杂度:O(MNk)。其中k为干扰源的数目,一共需要进行k次BFS,每次BFS的时间复杂度为O(MN)。另外,DP过程的时间复杂度为O(MN)

空间复杂度:O(MN)grid_newcheck_listdp等二维矩阵所占空间均为O(MN)


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/127443.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue中如何进行数据可视化雷达图展示

在Vue中进行数据可视化雷达图展示 数据可视化是将数据以图形方式呈现的过程&#xff0c;雷达图是其中一种常用的图表类型&#xff0c;用于可视化多个维度的数据。Vue.js作为一个流行的JavaScript框架&#xff0c;提供了许多工具和库来实现数据可视化。本文将介绍如何使用Vue来…

SpringBoot文件上传

前端 <form action"/upload" method"post" enctype"multipart/form-data">姓名: <input type"text" name"username"><br>年龄: <input type"text" name"age"><br>头像:…

【应用层协议】初始Http,fiddler的使用

文章目录 1. HTTP概念2. 下载fiddler及使用获得HTTP协议格式2.1 fiddler的下载2.2 fiddler使用 3. HTTP请求&#xff08;Request&#xff09;3.1 请求行3.1.1 URL3.1.2 方法3.1.2.1 GET3.1.2.2 POST3.1.2.3 其他方法 3.2 报头&#xff08;header&#xff09;3.3 空白行3.4 正文…

CentOS Stream9 安装远程桌面服务 Xrdp

1. 安装 XRDP 若服务器本身没有桌面则首先需要安装本地桌面&#xff1a; yum -y groups install "GNOME Desktop" startx配置源&#xff1a; dnf install epel-release安装 xrdp dnf install xrdp 2. 配置 Xrdp Xrdp 配置文件位于 /etc/xrdp 目录中。对于常规 X…

网络安全总结

前言 本文内容主要摘抄网络规划设计师的教材和腾讯-SUMMER课堂&#xff0c;主要对网络安全进行简单梳理和总结 OSI安全体系 X轴表示8种安全机制&#xff0c;Y轴表示OSI7层模型&#xff0c;Z轴表示5种安全服务&#xff0c;图中X是水平&#xff0c;Y轴竖直&#xff0c;Z轴向外…

Redis 获取、设置配置文件

以Ubuntu 为例 redis配置文件 cd /etc/redis sudo vim redis.conf 获取配置文件、修改配置文件

VS2022+qt5.15.2+cmake3.23.2配置VTK9.1.0版本

VS2022qt5.15.2cmake3.23.2VTK9.1.0 尝试了好多次&#xff0c;终于成了~ 软件安装 先把需要的软件都安装好&#xff01; VS2022安装教程: https://blog.csdn.net/qq_44005305/article/details/132295064 qt5.15.2安装教程&#xff1a;https://blog.csdn.net/Qi_1337/article…

在Unity使用自定义网格生成一个球体

1.在Unity场景中新建一个空物体&#xff0c;在空物体上添加MeshRenderer和MeshFilter组件。 2.新建一个C#脚本命名SphereMesh,将脚本挂载到空物体上&#xff0c;如图&#xff1a; 运行场景就可以看到生成一个球体 全部代码如下&#xff1a; using UnityEngine;public class S…

leetcode42 接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高…

Transformer预测 | Pytorch实现基于Transformer的时间序列预测(含单步与多步实验)

文章目录 效果一览文章概述模型描述程序设计单步实验多步实验参考资料效果一览 文章概述 Transformer预测 | Pytorch实现基于Transformer的时间序列预测(含单步与多步实验) Transformer-singlestep.py 包含单步预测模型 Transformer-multistep.py 包含多步预测模型 这是单步预…

BJT晶体管

BJT晶体管也叫双极结型三极管&#xff0c;主要有PNP、NPN型两种&#xff0c;符号如下&#xff1a; 中间的是基极&#xff08;最薄&#xff0c;用于控制&#xff09;&#xff0c;带箭头的是发射极&#xff08;自由电子浓度高&#xff09;&#xff0c;剩下的就是集电极&#xff0…

HashMapConcurrentHashMap

文章目录 1、HashMap基础类属性node容量负载因子hash算法 2、数组链表/树为什么引入链表为什么jdk1.8会引入红黑树为什么一开始不就使用红黑树&#xff1f;HashMap的底层数组取值的时候&#xff0c;为什么不用取模&#xff0c;而是&数组的长度为什么是2的次幂如果指定数组的…