通过率 0% · 提交 0 · 通过 0
视觉模型在提取特征时,会用一个 K×K 的卷积核在 H×W 的特征图上滑动。给定整数特征图 X、卷积核 Ker、步长 S 与零补边宽度 P,请计算卷积输出:输出第 (i, j) 格等于把核左上角对齐到补零后特征图的 (i·S, j·S) 位置后,窗口内逐元素乘积之和,即 sum(X[i·S + a - P][j·S + b - P] · Ker[a][b]),越界位置按 0 参与计算。输出高 OH = (H + 2P - K) / S + 1,宽 OW = (W + 2P - K) / S + 1,数据保证两个除法都整除。
这类题属于算法机考高频题型中「华为 AI 岗 / 卷积」方向的高频题型,通常考察对「华为 AI 岗 / 卷积」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
第一行输入 H W K S P。接下来 H 行,每行 W 个整数,表示特征图。最后 K 行,每行 K 个整数,表示卷积核。
输出 OH 行,每行 OW 个整数,用单个空格分隔。
示例 1
输入示例
3 3 2 1 0 1 2 3 4 5 6 7 8 9 1 0 0 -1
输出示例
-4 -4 -4 -4
3×3 输入、2×2 核、无补边步长 1
示例 2
输入示例
3 3 3 1 1 1 2 3 4 5 6 7 8 9 0 1 0 1 1 1 0 1 0
输出示例
7 11 11 17 25 23 19 29 23
补边 1 让输出尺寸等于输入
时间限制 3000 ms · 内存限制 256 MB
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
这些是真正决定能不能 AC、但通用题解里常被略过的点。
卷积的前向计算是深度学习最基础的算子,机考里把它出成纯模拟:四层循环、一条尺寸公式,考的是你能不能把下标关系一次写对。课程第 15 天的尺寸公式 (H + 2P - K) / S + 1 在这里直接用上,而且题面保证整除,连向下取整的分支都替你砍掉了。
两种写法。一种是真的构造一张 (H+2P)×(W+2P) 的新矩阵,边缘填 0,窗口取值永不越界,代码最顺;另一种是不构造新矩阵,取值时判断 0 <= 行 < H 且 0 <= 列 < W,越界按 0 算。两种都对,前者空间多一点但几乎不会写错,推荐考场用前者——省下的调试时间远比那点内存值钱。
输出格 (i, j) 对应的窗口,是把核的左上角对齐到补零图的 (i·S, j·S)。所以累加式是:
out[i][j] = sum( padded[i*S + a][j*S + b] * ker[a][b] ) # a, b 跑 0..K-1i、j 是输出坐标,a、b 是核内偏移,别把它们混着乘步长——步长只作用在输出坐标上。写完先拿示例 1 手过一格:out[0][0] = 1·1 + 2·0 + 4·0 + 5·(-1) = -4,对上了再往下写。
H、W ≤ 120,K ≤ 7,上限约 7×10⁵ 次乘加,四层朴素循环远在时限内——这道题没有部分分博弈,慢写法也能过,把正确性放在第一位。
Python 版先把 H+2P 行、W+2P 列的补零矩阵铺好,把原图拷进中间,然后四层循环照公式累加。读入用 sys.stdin.buffer.read().split() 一次切完再按数量取——特征图和核连着给,按行读容易错位。输出每行用 " ".join(map(str, row)),整数不涉及精度。
1. 示例 1 的 out[0][0]:1·1 + 2·0 + 4·0 + 5·(-1) = -4,核对下标对应关系。 2. K=1、核=[[1]]:输出应与输入(按步长抽样后)完全一致——单位核是恒等变换,验证你的窗口没有偏移。 3. P=1、K=3、S=1:输出尺寸应等于输入尺寸(same 卷积),第一格窗口有五个位置落在补零区,手算一遍确认越界都按 0 参与。
这三组分别卡「下标关系」「恒等性」「补零语义」,全对基本就稳了。
这道题就是第 15 天 conv 手撕任务的判题版:那天的 4×4 手算 trace 是这里的最小用例,写熟的四层循环直接照搬。做完可以顺手想一层:多通道卷积无非是把这套单通道流程逐通道跑一遍再逐位相加,参数量公式 C_in×K×K×C_out+C_out 里的每一项都能在这份代码里找到影子。
# 朴素卷积:先零补边构造新矩阵,再按尺寸公式 (H+2P-K)/S+1 跑四层循环
# i、j 是输出格坐标,a、b 是核内偏移,取 padded[i*S+a][j*S+b]
import sys
def main():
data = sys.stdin.buffer.read().split()
at = 0
H = int(data[at]); at += 1
W = int(data[at]); at += 1
K = int(data[at]); at += 1
S = int(data[at]); at += 1
P = int(data[at]); at += 1
nums = list(map(int, data[at:]))
X = [nums[i * W:(i + 1) * W] for i in range(H)]
ker = [nums[H * W + i * K:H * W + (i + 1) * K] for i in range(K)]
PH, PW = H + 2 * P, W + 2 * P
pad = [[0] * PW for _ in range(PH)]
for i in range(H):
pad[i + P][P:P + W] = X[i]
OH = (PH - K) // S + 1
OW = (PW - K) // S + 1
lines = []
for i in range(OH):
base_r = i * S
row = []
for j in range(OW):
base_c = j * S
acc = 0
for a in range(K):
pr = pad[base_r + a]
kr = ker[a]
for b in range(K):
acc += pr[base_c + b] * kr[b]
row.append(acc)
lines.append(" ".join(map(str, row)))
sys.stdout.write("\n".join(lines) + "\n")
main()
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有