华为OD机试(C卷+D卷)2024真题目录(Java & c++ & python)
题目描述
给定一个包含 0 和 1 的二维矩阵。
给定一个初始位置和速度,一个物体从给定的初始位置出发,在给定的速度下进行移动,遇到矩阵的边缘则发生镜面发射。
无论物体经过 0 还是 1,都不影响其速度。
请计算并给出经过 t 时间单位后,物体经过 1 点的次数。
矩阵以左上角位置为 [0, 0](列(x),行(y)),例如下面A点坐标为 [2, 1](第二列,第一行)
注意:
- 如果初始位置的点是 1,也计算在内
- 时间的最小单位为 1,不考虑小于 1 个时间单位内经过的点
输入描述
第一行为初始信息
<w><h><x><y><sx><sy><t>
第二行开始一共 h 行,为二维矩阵信息
其中:
- w,h 为矩阵的宽和高
- x,y 为起始位置
- sx,sy 为初始速度
- t 为经过的时间
所有输入都是有效的,数据范围如下:
- 0 < w < 100
- 0 < h < 100
- 0 ≤ x < w
- 0 ≤ y < h
- -1 ≤ sx ≤ 1
- -1 ≤ sy ≤ 1
- 0 ≤ t <100
输出描述
经过 1 的个数
注意初始位置也要计算在内
用例
输入
12 7 2 1 1 -1 13
001000010000
001000010000
001000010000
001000010000
001000010000
001000010000
001000010000
输出
3
说明
初始位置为(2,1),速度为(1,-1),那么13个时间单位后,经过点1的个数为3
解题思路
如果当前位置 x,y 按照速度 sx,sy 运动后,新位置越界的话,比如新位置x,y:
- x < 0
注意 -1 ≤ sx, sy ≤ 1,因此 x < 0 越界时必然 x = -1, 则经过反射,x = 1 - x >= w
注意 -1 ≤ sx, sy ≤ 1,因此 x >= w 越界时必然 x = w, 则经过反射,x = w - 2 - y < 0
注意 -1 ≤ sx, sy ≤ 1,因此 y < 0 越界时必然 y = -1,则经过反射,y = 1 - y >= h
注意 -1 ≤ sx, sy ≤ 1,因此 y >= h 越界时必然 y = h,则经过反射,y = h - 2
还需要注意的是,反射不仅会影响位置,而且会影响和后续的速度方向:
- 一旦新位置x越界,则后续速度 sx = -sx
- 一旦新位置y越界,则后续速度 sy = -sy
我们只要记录运动路径中遇到的元素1的个数即可。
C++、Java、Python代码如下:
C++参考代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int w, h, x, y, sx, sy, t;
cin >> w >> h >> x >> y >> sx >> sy >> t;
// 输入矩阵
string matrix[h];
for (int i = 0; i < h; i++) {
cin >> matrix[i];
}
int ans = 0;
while (t >= 0) {
// 注意本题横纵坐标是反的,因此y其实是行号,x是列号
if (matrix[y][x] == '1') {
ans++;
}
// 更新位置
y += sy;
x += sx;
// 处理 x 方向的反弹
if (x < 0) {
x = 1; // 反弹后位置为第二列
sx = -sx; // 水平方向速度反转
} else if (x >= w) {
x = w - 2; // 反弹后位置为倒数第二列
sx = -sx; // 水平方向速度反转
}
// 处理 y 方向的反弹
if (y < 0) {
y = 1; // 反弹后位置为第二行
sy = -sy; // 垂直方向速度反转
} else if (y >= h) {
y = h - 2; // 反弹后位置为倒数第二行
sy = -sy; // 垂直方向速度反转
}
t--; // 时间递减
}
cout << ans << endl; // 输出经过 '1' 的格子数
return 0;
}
Java参考代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 输入参数
int w = sc.nextInt(); // 矩阵的宽度
int h = sc.nextInt(); // 矩阵的高度
int x = sc.nextInt(); // 起始位置的 x 坐标(列)
int y = sc.nextInt(); // 起始位置的 y 坐标(行)
int sx = sc.nextInt(); // 水平速度
int sy = sc.nextInt(); // 垂直速度
int t = sc.nextInt(); // 总时间
// 读取矩阵
char[][] matrix = new char[h][w];
for (int i = 0; i < h; i++) {
matrix[i] = sc.next().toCharArray(); // 每一行输入转换为字符数组
}
int ans = 0; // 统计经过标记为 '1' 的格子的次数
while (t >= 0) {
// 注意:y 是行号,x 是列号
if (matrix[y][x] == '1') {
ans++;
}
// 更新物体位置
y += sy;
x += sx;
// 处理 x 方向的边界反弹
if (x < 0) {
x = 1; // 反弹后的位置
sx = -sx; // 反转水平速度
} else if (x >= w) { // 当超出右边界
x = w - 2; // 反弹后的位置
sx = -sx; // 反转水平速度
}
// 处理 y 方向的边界反弹
if (y < 0) {
y = 1; // 反弹后的位置
sy = -sy; // 反转垂直速度
} else if (y >= h) { // 当超出下边界
y = h - 2; // 反弹后的位置
sy = -sy; // 反转垂直速度
}
t--; // 时间递减
}
// 输出经过标记为 '1' 的格子的次数
System.out.println(ans);
}
}
Python参考代码
# 输入获取
w, h, x, y, sx, sy, t = map(int, input().split())
matrix = [input() for _ in range(h)]
ans = 0
while t >= 0:
# 注意本题横纵坐标是反的,因此y其实是行号,x是列号
if matrix[y][x] == '1':
ans += 1
y += sy
x += sx
if x < 0:
x = 1
sx = -sx
elif x >= w: # 注意本题横纵坐标是反的,因此x是列号,w是矩阵列数
x = w - 2
sx = -sx
if y < 0:
y = 1
sy = -sy
elif y >= h: # 注意本题横纵坐标是反的,因此y是行号,h是矩阵行数
y = h - 2
sy = -sy
t -= 1
print(ans)