青训营X豆包MarsCode 技术训练营:AI刷题笔记-01 | 豆包MarsCode AI 刷题

95 阅读3分钟

AI刷题笔记01

题目描述:唐门绝技:暴雨梨花针最少发射次数

在唐门,外门弟子唐三发现了一种强大的暗器技巧,名为暴雨梨花针,它能在一条直线上推毁所有目标。唐三在一本古籍中学习到了这门技巧,为了练习,他设置了若干个靶子在二维平面上。每个靶子是一条垂直于X轴的线段,由三个参数 x_{left},x_{right},y描述,其中y是固定的高度,x_{left}和x{right} 表示线段在X轴上的起止位置。 唐三的目标是使用尽可能少的暴雨梨花针来击中所有靶子。由于暴雨梨花针的珍贵,每次射击必须经济有效。每次射击暴雨梨花针都将从某个x值发射,能垂直上升到y=100。 请你帮助唐三计算最少需要多少次射击,才能保证击中所有靶子。结果需对给定的P取余。

样例1:

输入:k=4,p=100,target=[[10,26,3],[4,8,29],[1,5,8],[9,9,9]] 输出:3

解题核心思路

可以将其转化为“区域覆盖问题”,目标是尽可能少的使用垂直射击(即用尽可能少的区间覆盖所有靶子)。

解题步骤
题目分析
  • 每个靶子是一个垂直于 X 轴的线段 [X(left),X(right)],位于固定的 y 值。
  • 一次射击可以覆盖若干个线段,只要这些线段在 x 轴上有重叠部分。
编程策略
  • 按照区间的 X(right) 升序排序。
  • 用贪心方法选取尽可能少的区间,使得所有靶子都被覆盖。
算法设计
  • 对 target 按照X(right)排序。
  • 初始化一个变量 last_shot表示上一次射击的位置(初始为负无穷)。
  • 遍历每个靶子,如果当前靶子未被覆盖,在 X(right) 处射击并更新last_shot。
  • 记录射击次数,并对结果取模。
代码编写
    # 按照 x_right 升序排序
    target.sort(key=lambda t: t[1])
    last_shot = float('-inf')
    shots = 0

    for x_left, x_right, y in target:
        # 如果当前靶子未被覆盖
        if x_left > last_shot:
            # 在 x_right 处射击
            last_shot = x_right
            shots += 1

    # 对结果取模
    return shots % p

# 测试样例
k = 4
p = 100
target = [[10, 26, 3], [4, 8, 29], [1, 5, 8], [9, 9, 9]]
print(solution(k, p, target))  # 输出: 3
补充说明
  • 按右端点排序确保我们总是选择最小的 X(right)来覆盖尽可能多的靶子。
  • 如果当前靶子未被覆盖,意味着必须新射击。选择其右端点是最优的,因为能覆盖后续可能重叠的靶子。因为要符合经济性原理,因此,选择靶子的最右端的坐标作为暗器的发射点X能够尽可能最大的覆盖到多个靶子(同理,可将发射坐标X换成靶子最左点)
结语

这道题目是我作为一位编程新手所遇到的较为困难的题目之一,期间也是花费较多的时间进行思考与理解,AI在其中也扮演着非常重要的角色,无论是思维的拓展,还是代码的讲解,都节省了我的很多精力,使得我对于AI在各行各业中的运用保持着更加乐观的态度。