华为OD机试D卷C卷 - 多段线数据压缩(C++ Java JavaScript Python C语言)

本文介绍了华为OD机考中的一道数据压缩问题,涉及多段线简化。通过判断拐点来压缩坐标列表,保证输出顺序不变。提供了C++、Java、JavaScript、Python和C语言的解题思路及代码示例。

题目描述

下图中,每个方块代表一个像素,每个像素用其行号和列号表示。为简化处理,多段线的走向只能是水平、竖直、斜向45度。

image-20231210160526758

上图中的多段线可以用下面的坐标串表示:(2, 8), (3, 7), (3, 6), (3, 5), (4, 4), (5, 3), (6, 2), (7, 3), (8, 4), (7, 5)。

但可以发现,这种表示不是最简的,其实只需要存储6个蓝色的关键点即可,它们是线段的起点、拐点、终点,而剩下4个点是冗余的。

即可以简化为:(2,8)、(3,7)、(3,5)、(6,2)、(8,4)、(7,5)

现在,请根据输入的包含有冗余数据的多段线坐标列表,输出其最简化的结果。

输入描述

2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5

1、所有数字以空格分隔,每两个数字一组,第一个数字是行号,第二个数字是列号;

2、行号和列号范围为[0,64),用例输入保证不会越界,考生不必检查;

3、输入数据至少包含两个坐标点。

输出描述

2 8 3 7 3 5 6 2 8 4 7 5

压缩后的最简化坐标列表,和输入数据的格式相同。

备注: 输出的坐标相对顺序不能变化。

用例

输入

2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5

输出

2 8 3 7 3 5 6 2 8 4 7 5

说明

如上图所示,6个蓝色像素的坐标依次是(2,8)、(3,7)、(3,5)、(6,2)、(8,4)、(7,5)。

解题思路

遍历输入的坐标点列表,对于每个当前考察的点 curr,检查它是否是拐点。为此,比较它与前一个点 prev 以及后一个点 next 形成的两个向量。如果这两个向量不共线(即它们的叉积不为零),则当前点是一个拐点。

向量和向量的叉积(cross product)。

  1. 向量:在二维平面中,向量可以用来表示两点之间的方向和距离。在这段代码中,向量是由两个点确定的,例如,向量 (dx1, dy1) 是由点 prev 指向点 curr 的向量,而向量 (dx2, dy2) 是由点 curr 指向点 next 的向量。

  2. 向量的叉积:在二维空间中,两个向量 a(x1, y1)b(x2, y2) 的叉积定义为 a.x * b.y - a.y * b.x

### 华为OD分糖果问题的Python解题思路 #### 问题描述 小明从糖果盒中随意抓取一定数量的糖果,每次可以执行三种操作之一:取出一半糖果并舍去余数;如果当前糖果数目为奇数,则可以从盒子中再拿一个糖果或将手里的一个糖果放回去。目标是最少经过几次这样的操作能够使手中的糖果变为一颗。 为了达到这个目的,采用贪心策略来解决问题[^3]。具体来说,在每一步都尽可能快速地减少糖果的数量直到只剩下一颗为止。当遇到奇数个糖果时,优先考虑加一而不是减一,因为这样可以在下一轮更有效地通过除以2的方式大量削减糖果总数。 #### 贪婪算法分析 对于任意正整数n表示初始糖果数: - 如果 n 是偶数,则直接将其除以2; - 若 n 为奇数,则判断 (n+1)/2 和 (n−1)/2 的大小关系,选择较小的那个作为下一步的结果,这是因为我们希望更快接近1。 这种做法基于这样一个事实——当我们面对两个连续的奇数值时,较大的那个总是可以通过增加1变成一个小得多的新值(即其半数),而较小的一个则需要两次操作才能完成同样的效果(先减后除)[^4]。 #### Python代码实现 下面给出了解决上述问题的具体Python程序: ```python def min_steps_to_one(n): steps = 0 while n != 1: if n % 2 == 0: n //= 2 elif ((n + 1) // 2) < ((n - 1) // 2): n += 1 else: n -= 1 steps += 1 return steps if __name__ == "__main__": candy_count = int(input().strip()) print(min_steps_to_one(candy_count)) ``` 此函数接收一个参数`n`代表起始的糖果数量,并返回将这些糖果减少到只有一个所需的最小步数。主程序部分读入用户输入的数据并调用该方法打印最终结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值