通过率 0% · 提交 0 · 通过 0
这道 OJ 的配套动画
卷积窗口计算 · 对应本题的思路、过程和代码
视觉模型在提取特征时,会用一个 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 <= H, W <= 120;1 <= K <= 7 且 K <= min(H, W) + 2P;1 <= S <= 4;0 <= P <= 6;保证 (H + 2P - K) 与 (W + 2P - K) 都能被 S 整除;特征图元素绝对值不超过 100,核元素绝对值不超过 10,可能为负数。
示例 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
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
输出示例
7 11 11 17 25 23 19 29 23
补边 1 让输出尺寸等于输入
时间限制 3000 ms · 内存限制 256 MB
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有
这些是真正决定能不能 AC、但通用题解里常被略过的点。
根据 OH=(H+2P-K)/S+1、OW=(W+2P-K)/S+1 计算输出尺寸。可以先构造补零后的矩阵,也可以访问原矩阵时判断边界。对每个输出位置 (i,j),枚举卷积核内的 (a,b),累加 X[iS+a-P][jS+b-P]·Ker[a][b],越界项按 0 处理。
输出位置 (i,j) 的窗口左上角由步长唯一确定。双重核内循环枚举该窗口与卷积核的全部对应位置,越界位置贡献为 0,因而累加结果与题目定义的单通道卷积完全一致。所有输出坐标均被处理一次。
时间复杂度为 O(OH·OW·K²)。若显式构造补零矩阵,额外空间为 O((H+2P)(W+2P));边界判断写法除输出外只需常数额外空间。
尺寸公式末尾不能漏掉 +1;步长只乘输出坐标,不乘核内偏移。题目使用零补边,核元素和输入元素都可能为负数。
# 朴素卷积:先零补边构造新矩阵,再按尺寸公式 (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()