1 条题解

  • 0
    @ 2025-11-11 10:41:51

    题目理解

    我们有 NN 个员工,每人有一个离开时间 SiS_i 和返回时间 TiT_i。我们最多可以分配 KK 把钥匙。

    关键规则

    • 时刻 00 门是关着的
    • 有钥匙的员工离开时可以关门,没有钥匙的员工离开时门会保持开着的状态
    • 员工返回时,如果门关着且自己有钥匙,可以开门进入;如果门开着,可以直接进入
    • 目标:最大化门关着的时间

    关键观察

    1. 时间线分析

    我们可以将所有事件(离开和返回)按时间顺序排列。每个员工对应两个事件:

    • 离开事件 (Si,out,i)(S_i, \text{out}, i)
    • 返回事件 (Ti,in,i)(T_i, \text{in}, i)

    2. 钥匙的作用

    • 如果员工有钥匙,离开时可以选择关门
    • 如果员工没有钥匙,离开时不能关门(门会保持开着)

    3. 状态转移

    门的状态变化:

    • 初始状态:关着
    • 当有钥匙的员工离开时:可以保持关着或变成开着
    • 当没有钥匙的员工离开时:必须变成开着
    • 当员工返回时:如果门关着且员工有钥匙,可以开门进入;如果门开着,可以直接进入

    动态规划解法

    状态设计

    dp[i][j] 表示考虑前 ii 个事件,已经分配了 jj 把钥匙时,门关着的最大时间。

    但是直接这样定义状态不够,我们还需要知道当前门的状态。

    更好的状态设计: dp[i][j][state] 表示考虑前 ii 个事件,分配了 jj 把钥匙,当前门的状态为 state(0=开,1=关)时的最大关门时间。

    状态转移

    对于每个事件,我们考虑两种情况:给当前员工钥匙或不给钥匙。

    离开事件

    • 如果有钥匙:可以选择关门或不关门
    • 如果没有钥匙:必须让门开着

    返回事件

    • 如果有钥匙:可以进入(无论门的状态)
    • 如果没有钥匙:只有当门开着时才能进入

    算法步骤

    1. 将所有 2N2N 个事件按时间排序
    2. 初始化 DP:dp[0][0][1] = 0(时刻0门关着)
    3. 按时间顺序处理每个事件:
      • 如果是离开事件:
        • 如果分配钥匙:可以保持当前状态或改变为关门状态
        • 如果不分配钥匙:必须变为开门状态
      • 如果是返回事件:
        • 如果分配钥匙:可以保持当前状态
        • 如果不分配钥匙:必须当前是开门状态
    4. 计算时间贡献:在事件间隔期间,如果门关着,就累加关门时间

    贪心 + 动态规划优化

    观察发现:如果我们给一个员工钥匙,那么我们可以控制他在离开时是否关门。最优策略通常是让有钥匙的员工在离开时尽量关门。

    我们可以这样思考:

    1. 初始时门是关着的
    2. 当没有钥匙的员工离开时,门必须打开,直到下一个有钥匙的员工离开时才能关门
    3. 因此,问题转化为:选择 KK 个员工作为"关键点",使得这些关键点之间的间隔(门开着的时间)最小

    更精确的解法:

    • 将时间线分段,每段以没有钥匙的员工离开开始,以有钥匙的员工离开结束
    • 我们要最小化这些段的长度之和

    总结

    这道题的关键在于:

    1. 理解钥匙的作用:控制门的状态变化
    2. 事件序列分析:按时间顺序处理离开和返回事件
    3. 状态设计:跟踪钥匙分配数量和门的状态
    4. 优化思维:将最大化关门时间转化为最小化开门时间

    通过合理的状态设计和动态规划,我们可以在多项式时间内解决这个问题。

    • 1

    信息

    ID
    5220
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者