大厂秋招真题【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的矩阵),计算出连线的最小干扰度。
输入描述
第一行是两个整数M和N(M和N最大值为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_new、check_list、dp等二维矩阵所占空间均为O(MN)。
华为OD算法/大厂面试高频题算法练习冲刺训练
-
华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!
-
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
-
60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁
-
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
-
可查看链接 大厂真题汇总 & OD真题汇总(持续更新)
-
绿色聊天软件戳
od1336了解更多
相关文章:
大厂秋招真题【BFS+DP】华为20230921秋招T3-PCB印刷电路板布线(留学生专场)
华为20230921秋招T3-PCB印刷电路板布线(留学生专场) 题目描述与示例 题目描述 在PCB印刷电路板设计中,器件之间的连线,要避免线路的阻抗值增大,而且器件之间还有别的器任和别的干扰源,在布线时我们希望受…...
OpenCV Python – 使用SIFT算法实现两张图片的特征匹配
OpenCV Python – 使用SIFT算法实现两张图片的特征匹配 1.要实现在大图中找到任意旋转、缩放等情况下的小图位置,可以使用特征匹配算法,如 SIFT (尺度不变特征变换) 或 SURF (加速稳健特征)。这些算法可以在不同尺度和旋转情况下寻找匹配的特征点 impo…...
doc转html后添加style和导航
public static void main(String[] args) throws Exception {docxToHtml(); } public static void docxToHtml() throws Exception {//D:\zpdtolly\工作总结文档\zpd使用文档\v4\用户使用手册\客户端使用手册String sourceFileName "C:\\Users\\luoguoqing\\Desktop\\202…...
Python中跨越多个文件使用全局变量
嗨喽,大家好呀~这里是爱看美女的茜茜呐 这个琐碎的指南是关于在 Python 中跨多个文件使用全局变量。 但是在进入主题之前,让我们简单地看看全局变量和它们在多个文件中的用途。 👇 👇 👇 更多精彩机密、教程ÿ…...
设计模式 - 解释器模式
目录 一. 前言 二. 实现 三. 优缺点 一. 前言 解释器模式(Interpreter Pattern)指给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子,属于行为型设计模式。是…...
javascript禁止鼠标右键和复制功能
要禁止鼠标右键和复制功能,可以编写如下的封装函数: function preventDefaultCopy(event) {// 禁止右键 菜单和复制event.preventDefault();event.stopPropagation();return false; }// 在需要禁止复制的元素上添加该事件监听器 element.addEventListen…...
WebDAV之π-Disk派盘 + 咕咚云图
咕咚云图是一款强大的图床传图软件,它能够让您高效地对手机中的各种图片进行github传输,多个平台快速编码上传,支持远程删除不需要的图片,传输过程安全稳定,让您可以很好的进行玩机或者其他操作。 可帮你上传手机图片到图床上,并生成 markdown 链接,支持七牛云、阿里云…...
C语言-数组
C 语言支持数组数据结构,数组是一个由若干相同类型变量组成的有序集合。 这里的有序是指数组元素在内存中的存放方式是有序的,即所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。 在 C 语言中&am…...
Linux UWB Stack实现——MCPS调度接口(API)
在上一篇文章中,介绍了MCPS调度接口涉及的相关数据结构实现MCPS调度接口(数据结构),本文继续介绍调度相关的方法的实现。 1. 域处理 1.1 域注册与注销 注册/注销一个mcps802154_region,分别在模块加载(mo…...
el-tree中插入图标并且带提示信息
<template><div class"left"><!-- default-expanded-keys 默认展开 --><!-- expand-on-click-node 只有点击箭头才会展开树 --><el-tree :data"list" :props"defaultProps" node-click"handleNodeClick" :…...
竞赛选题 深度学习 YOLO 实现车牌识别算法
文章目录 0 前言1 课题介绍2 算法简介2.1网络架构 3 数据准备4 模型训练5 实现效果5.1 图片识别效果5.2视频识别效果 6 部分关键代码7 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于yolov5的深度学习车牌识别系统实现 该项目较…...
Direct3D网格(一)
创建网格 我们可以用D3DXCreateMeshFVF函数创建一个"空"网格对象 ,空网格对象是指我们指定了网格的面片总数和顶点总数,然后由该函数为顶点缓存、索引缓存和属性缓存分配大小合适的内存,之后即可手工填入网格数据。 HRESULT WINA…...
C语言打印菱形
一、运行结果图 二、源代码 # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值;int line 0;int i 0;int j 0;//获取变量值;scanf("%d", &line);//循环打印上半部分;for (i 0; i <…...
ElasticSearch搜索引擎:数据的写入流程
一、ElasticSearch 写数据的总体流程: (1)ES 客户端选择一个节点 node 发送请求过去,这个节点就是协调节点 coordinating node (2)协调节点对 document 进行路由,通过 hash 算法计算出数据应该…...
python3 调用 另外一个python脚本
3种python调用其他脚本脚本的方法_python 调用python脚本_linjingyg的博客-CSDN博客 Python之系统交互(调用系统命令)subprocess_subprocess.getoutput(cmd) 参数格式不正确-CSDN博客 subprocess.call()只能返回状态码。subprocess.getoutput(cmd)只能输出命令结果。 str(py…...
【13】c++设计模式——>简单工厂模式
工厂模式的定义 c中的工厂模式是一种创建型设计模式,它提供一种创建对象的接口,但具体创建的对象类型可以在运行时决定,这样可以将对象的创建与使用代码分离,提高代码的灵活性和可维护性。 在c中实现工厂模式,通常会定…...
系统架构设计:2 论软件设计方法及其应用
目录 一 软件设计方法 1结构化设计 2信息工程 3面向对象设计 4原型设计...
基于Winform的UDP通信
1、文件结构 2、UdpReceiver.cs using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks;namespace UDPTest.Udp {public class UdpStateEventArgs : EventArgs…...
掌握 BERT:自然语言处理 (NLP) 从初级到高级的综合指南(1)
简介 BERT(来自 Transformers 的双向编码器表示)是 Google 开发的革命性自然语言处理 (NLP) 模型。它改变了语言理解任务的格局,使机器能够理解语言的上下文和细微差别。在本文[1]中,我们将带您踏上从 BERT 基础知识到高级概念的旅…...
Linux Ftrace介绍
文章目录 一、简介二、内核函数调用跟踪参考链接: 一、简介 Ftrace 是 Linux 官方提供的跟踪工具,在 Linux 2.6.27 版本中引入。Ftrace 可在不引入任何前端工具的情况下使用,让其可以适合在任何系统环境中使用。 Ftrace 可用来快速排查以下相…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
