移除盒子(进阶版:带颜色限制的移除成本)
字数 4407 2025-12-14 20:32:02

移除盒子(进阶版:带颜色限制的移除成本)


题目描述

你面前有一排盒子,每个盒子有一个颜色(用正整数表示),这些盒子排成一列。
你可以进行以下操作:

  • 选择一个盒子,然后移除它。但移除操作有特殊的计分规则
    如果你移除了某个颜色为 \(c\) 的盒子,你获得的分数是:

\[ \text{score} = (\text{本次移除的连续同色盒子数量})^2 - \text{cost}(c) \]

其中 \(\text{cost}(c)\) 是一个给定的函数,表示移除颜色 \(c\) 的单个盒子的“固定成本”(正值表示成本,会减少分数,负值表示奖励,会增加分数)。

注意:

  1. 你一次可以移除一个或多个连续相同颜色的盒子(即必须一次性把一段连续相同颜色的盒子全部移除)。
  2. 移除后,两边的盒子会靠拢,成为相邻。
  3. 你可以任意选择移除的顺序,目标是最大化总得分

给定一个整数数组 boxes 表示盒子的颜色序列,以及一个函数 \(\text{cost}(c)\) 返回整数(可能是正、负或零),求最大得分。


示例

盒子序列:[1, 3, 2, 2, 2, 3, 4, 3, 1]
cost(1) = 1, cost(2) = 1, cost(3) = 2, cost(4) = 5

一个可能的操作顺序:

  • 先移除 [2,2,2],得分 = 3² - 1×3 = 9 - 3 = 6
  • 剩下 [1,3,3,4,3,1]
  • 移除 [3,3],得分 = 2² - 2×2 = 4 - 4 = 0
  • 剩下 [1,4,3,1]
  • 移除 [4],得分 = 1² - 5×1 = 1 - 5 = -4
  • 剩下 [1,3,1]
  • 移除 [3],得分 = 1² - 2×1 = 1 - 2 = -1
  • 剩下 [1,1]
  • 移除 [1,1],得分 = 2² - 1×2 = 4 - 2 = 2
    总得分 = 6 + 0 - 4 - 1 + 2 = 3

但这个顺序不一定是最优的,我们需要找到最大得分的策略。


解题思路

这是一个区间动态规划问题,但它比经典的“移除盒子”(Remove Boxes)更复杂,因为每个颜色有不同的移除成本,而且移除一段连续同色盒子时,成本是乘以盒子数量。

我们可以这样定义状态:
\(dp[i][j][k]\) 表示在区间 \([i, j]\) 上,在区间左侧(即 \(i\) 位置盒子的左边,但仍在整个序列范围内)有 \(k\) 个颜色与 \(boxes[i]\) 相同的盒子(这 \(k\) 个盒子是之前因为中间某些盒子被移除而暴露出来的,可以与 \(i\) 位置的盒子一起移除,以获得更高分数)。

举例:
对于 [A, ..., A, ...],如果 \(i\) 位置是 A,而 \(i\) 左边的若干 A 因为中间盒子被移除而可以合并进来,我们用 \(k\) 记录左边可合并的同色盒子数量。


状态转移推导

我们考虑对区间 \([i, j]\) 的第一个盒子(即 \(boxes[i]\))如何处理:

情况1:将 \(i\) 位置与它左边的 \(k\) 个同色盒子一起移除

我们找到区间内所有颜色等于 \(boxes[i]\) 的盒子,并决定是一次性把所有能合并的(包括左边的 \(k\) 个)一起移除,还是先处理中间部分,让更多同色盒子聚集后再一起移除。

\(m\) 是满足 \(i \le m \le j\)\(boxes[m] = boxes[i]\) 的位置集合。
我们可以选择在某个 \(p\) 位置(\(p\)\(m\) 集合中的某个位置,比如第一个匹配的位置)将区间分割,让左边部分与 \(k\) 合并,右边部分单独处理。

但更通用的转移是:

  • \(i\) 与后面某个同色位置 \(m\) 及它们之间的所有盒子一起考虑移除,但这样会涉及中间盒子的处理,比较复杂。

经典“移除盒子”问题的转移是:

\[dp[i][j][k] = \max \begin{cases} (k+1)^2 - \text{cost}(c) \times (k+1) + dp[i+1][j][0], & \text{如果 } i=j \\ \max_{m: i < m \le j, \, boxes[m]=boxes[i]} \left[ dp[i+1][m-1][0] + dp[m][j][k+1] \right], & \text{否则} \end{cases} \]

但这个公式是假设一次移除只能移除连续的一段同色盒子,并且在移除盒子 \(i\) 时,我们可以选择将它与后面的同色盒子 \(m\) 及中间的盒子先处理掉,然后 \(m\) 盒子就可以与前面的 \(k+1\) 个盒子(包括 \(i\) 位置)一起移除。

但本题中一次移除必须是连续同色的盒子,所以“与后面同色盒子一起移除”意味着必须把中间不同色的盒子先清空,然后两段同色的盒子才能变成相邻,从而一起移除。
这正是经典“移除盒子”的状态转移逻辑。


因此我们直接采用“移除盒子”的标准 DP 思路,但在计算得分时,修改得分公式。

状态:
\(dp[i][j][k]\) 表示在子数组 \(boxes[i..j]\) 上,在子数组前面(即 \(i\) 的左边,不在 \([i,j]\) 区间内)有 \(k\) 个颜色等于 \(boxes[i]\) 的盒子(这些盒子是之前保留下来,准备与 \(boxes[i]\) 一起移除的)。

目标:\(dp[0][n-1][0]\)

转移方程:

  1. 如果 \(i > j\)\(dp = 0\)
  2. 如果 \(i = j\),则我们可以选择移除这个盒子与它左边的 \(k\) 个盒子(都是同色),得分为:

\[ (k+1)^2 - (k+1) \times \text{cost}(boxes[i]) \]

  1. 如果 \(i < j\),我们考虑两种选择:
    • 选择1:现在就移除 \(i\) 与它左边的 \(k\) 个盒子(即 \(k+1\) 个同色盒子一起移除),然后处理剩下的区间 \([i+1, j]\),此时左边没有同色盒子累积,所以:

\[ \text{score}_1 = (k+1)^2 - (k+1) \times \text{cost}(boxes[i]) + dp[i+1][j][0] \]

  • 选择2:不立即移除 \(i\),而是保留 \(i\),让它与后面某个同色的盒子 \(m\) 一起移除。为了做到这一点,我们必须先移除区间 \([i+1, m-1]\) 内的所有盒子,这样 \(i\)\(m\) 才能相邻,并与左边的 \(k\) 个盒子一起移除。
    所以我们枚举 \(m \in (i, j]\)\(boxes[m] = boxes[i]\),然后:

\[ \text{score}_2 = dp[i+1][m-1][0] + dp[m][j][k+1] \]

 这里的 $dp[m][j][k+1]$ 表示在区间 $[m, j]$ 上,左边已经有 $k+1$ 个同色盒子(原来的 $k$ 个加上位置 $i$ 的盒子),这些将在后续一起移除。

取两种选择的最大值:

\[ dp[i][j][k] = \max(\text{score}_1, \max_{m} \text{score}_2) \]


算法步骤

  1. 输入数组 boxes 和 cost 函数。
  2. 预处理:对每个区间 \([i, j]\)\(k\) 计算 dp 值。
    注意 \(k\) 最大可能为 \(n\),但实际不会超过区间内同色盒子的总数,可以用记忆化搜索优化。
  3. 采用记忆化搜索实现:
    • 如果 \(i > j\),返回 0。
    • 如果已计算过 \(dp[i][j][k]\),直接返回。
    • 否则,先计算选择1的得分。
    • 然后遍历 \(m = i+1\)\(j\),如果 \(boxes[m] = boxes[i]\),递归计算:

\[ \text{temp} = dfs(i+1, m-1, 0) + dfs(m, j, k+1) \]

 更新最大值。
  • 记录结果并返回。
  1. 最终结果 = \(dfs(0, n-1, 0)\)

复杂度分析

  • 状态数:\(O(n^3)\),因为 \(i, j, k\)\(O(n)\)
  • 每个状态转移需要遍历可能的 \(m\),最坏 \(O(n)\),总复杂度 \(O(n^4)\),在 \(n \le 100\) 时可接受。
    优化:可以在预处理时记录每个区间内下一个同色盒子的位置,减少枚举,但最坏情况仍然是 \(O(n^4)\)
  • 空间复杂度:\(O(n^3)\)

示例演算(简略)

boxes = [1, 2, 1],cost(1)=1, cost(2)=1 为例:

  • 计算 dp[0][2][0]:
    • 选择1:移除 boxes[0] 和左边0个同色盒子,得分 = 1² - 1×1 = 0,加上 dp[1][2][0] 的结果。
    • 选择2:找到 m=2(同色1),则 temp = dp[1][1][0] + dp[2][2][1]。
      • dp[1][1][0]:移除 boxes[1] 单独,得 1² - 1×1 = 0。
      • dp[2][2][1]:移除 boxes[2] 与左边1个同色盒子(共2个同色盒子),得 2² - 2×1 = 4 - 2 = 2。
        所以 temp = 0 + 2 = 2。
    • 比较:选择1需要先算 dp[1][2][0]:
      dp[1][2][0]:boxes[1] 与 boxes[2] 不同,选择1:移除 boxes[1] 单独,得0,加 dp[2][2][0] = 0,总0;
      选择2:无同色 m,所以 dp[1][2][0] = 0。
      所以选择1总分 = 0 + 0 = 0。
    • 因此 dp[0][2][0] = max(0, 2) = 2。

最终结果 2,对应操作顺序:先移除中间的 2(得分0),剩下 [1,1] 一起移除(得分 2² - 1×2 = 2),总得分 2。


小结

本题是“移除盒子”的扩展,加入了颜色相关的移除成本。
关键点在于状态定义和转移方程的设计,特别是“左边保留的同色盒子数 k”这一维状态,使得我们可以推迟移除,以积累同色盒子获得更高的平方收益,同时减去对应的成本。

移除盒子(进阶版:带颜色限制的移除成本) 题目描述 你面前有一排盒子,每个盒子有一个颜色(用正整数表示),这些盒子排成一列。 你可以进行以下操作: 选择一个盒子,然后移除它。但移除操作有 特殊的计分规则 : 如果你移除了某个颜色为 \(c\) 的盒子,你获得的分数是: \[ \text{score} = (\text{本次移除的连续同色盒子数量})^2 - \text{cost}(c) \] 其中 \(\text{cost}(c)\) 是一个给定的函数,表示移除颜色 \(c\) 的单个盒子的“固定成本”(正值表示成本,会减少分数,负值表示奖励,会增加分数)。 注意: 你一次可以移除 一个或多个连续相同颜色的盒子 (即必须一次性把一段连续相同颜色的盒子全部移除)。 移除后,两边的盒子会靠拢,成为相邻。 你可以任意选择移除的顺序,目标是 最大化总得分 。 给定一个整数数组 boxes 表示盒子的颜色序列,以及一个函数 \(\text{cost}(c)\) 返回整数(可能是正、负或零),求最大得分。 示例 盒子序列: [1, 3, 2, 2, 2, 3, 4, 3, 1] cost(1) = 1, cost(2) = 1, cost(3) = 2, cost(4) = 5 一个可能的操作顺序: 先移除 [2,2,2] ,得分 = 3² - 1×3 = 9 - 3 = 6 剩下 [1,3,3,4,3,1] 移除 [3,3] ,得分 = 2² - 2×2 = 4 - 4 = 0 剩下 [1,4,3,1] 移除 [4] ,得分 = 1² - 5×1 = 1 - 5 = -4 剩下 [1,3,1] 移除 [3] ,得分 = 1² - 2×1 = 1 - 2 = -1 剩下 [1,1] 移除 [1,1] ,得分 = 2² - 1×2 = 4 - 2 = 2 总得分 = 6 + 0 - 4 - 1 + 2 = 3 但这个顺序不一定是最优的,我们需要找到最大得分的策略。 解题思路 这是一个区间动态规划问题,但它比经典的“移除盒子”(Remove Boxes)更复杂,因为每个颜色有不同的移除成本,而且移除一段连续同色盒子时,成本是乘以盒子数量。 我们可以这样定义状态: 设 \(dp[ i][ j][ k]\) 表示在区间 \([ i, j]\) 上, 在区间左侧 (即 \(i\) 位置盒子的左边,但仍在整个序列范围内)有 \(k\) 个颜色与 \(boxes[ i ]\) 相同的盒子(这 \(k\) 个盒子是之前因为中间某些盒子被移除而暴露出来的,可以与 \(i\) 位置的盒子一起移除,以获得更高分数)。 举例: 对于 [A, ..., A, ...] ,如果 \(i\) 位置是 A,而 \(i\) 左边的若干 A 因为中间盒子被移除而可以合并进来,我们用 \(k\) 记录左边可合并的同色盒子数量。 状态转移推导 我们考虑对区间 \([ i, j]\) 的第一个盒子(即 \(boxes[ i ]\))如何处理: 情况1:将 \(i\) 位置与它左边的 \(k\) 个同色盒子一起移除 我们找到区间内所有颜色等于 \(boxes[ i ]\) 的盒子,并决定是一次性把所有能合并的(包括左边的 \(k\) 个)一起移除,还是先处理中间部分,让更多同色盒子聚集后再一起移除。 设 \(m\) 是满足 \(i \le m \le j\) 且 \(boxes[ m] = boxes[ i ]\) 的位置集合。 我们可以选择在某个 \(p\) 位置(\(p\) 是 \(m\) 集合中的某个位置,比如第一个匹配的位置)将区间分割,让左边部分与 \(k\) 合并,右边部分单独处理。 但更通用的转移是: 将 \(i\) 与后面某个同色位置 \(m\) 及它们之间的所有盒子一起考虑移除,但这样会涉及中间盒子的处理,比较复杂。 经典“移除盒子”问题的转移是: \[ dp[ i][ j][ k ] = \max \begin{cases} (k+1)^2 - \text{cost}(c) \times (k+1) + dp[ i+1][ j][ 0 ], & \text{如果 } i=j \\ \max_ {m: i < m \le j, \, boxes[ m]=boxes[ i]} \left[ dp[ i+1][ m-1][ 0] + dp[ m][ j][ k+1] \right ], & \text{否则} \end{cases} \] 但这个公式是假设一次移除只能移除连续的一段同色盒子,并且在移除盒子 \(i\) 时,我们可以选择将它与后面的同色盒子 \(m\) 及中间的盒子先处理掉,然后 \(m\) 盒子就可以与前面的 \(k+1\) 个盒子(包括 \(i\) 位置)一起移除。 但本题中一次移除必须是连续同色的盒子,所以“与后面同色盒子一起移除”意味着必须把中间不同色的盒子先清空,然后两段同色的盒子才能变成相邻,从而一起移除。 这正是经典“移除盒子”的状态转移逻辑。 因此我们直接采用“移除盒子”的标准 DP 思路,但在计算得分时,修改得分公式。 状态: \(dp[ i][ j][ k]\) 表示在子数组 \(boxes[ i..j]\) 上, 在子数组前面 (即 \(i\) 的左边,不在 \([ i,j]\) 区间内)有 \(k\) 个颜色等于 \(boxes[ i]\) 的盒子(这些盒子是之前保留下来,准备与 \(boxes[ i ]\) 一起移除的)。 目标:\(dp[ 0][ n-1][ 0 ]\) 转移方程: 如果 \(i > j\),\(dp = 0\)。 如果 \(i = j\),则我们可以选择移除这个盒子与它左边的 \(k\) 个盒子(都是同色),得分为: \[ (k+1)^2 - (k+1) \times \text{cost}(boxes[ i ]) \] 如果 \(i < j\),我们考虑两种选择: 选择1:现在就移除 \(i\) 与它左边的 \(k\) 个盒子(即 \(k+1\) 个同色盒子一起移除),然后处理剩下的区间 \([ i+1, j ]\),此时左边没有同色盒子累积,所以: \[ \text{score}_ 1 = (k+1)^2 - (k+1) \times \text{cost}(boxes[ i]) + dp[ i+1][ j][ 0 ] \] 选择2:不立即移除 \(i\),而是保留 \(i\),让它与后面某个同色的盒子 \(m\) 一起移除。为了做到这一点,我们必须先移除区间 \([ i+1, m-1 ]\) 内的所有盒子,这样 \(i\) 和 \(m\) 才能相邻,并与左边的 \(k\) 个盒子一起移除。 所以我们枚举 \(m \in (i, j]\) 且 \(boxes[ m] = boxes[ i ]\),然后: \[ \text{score}_ 2 = dp[ i+1][ m-1][ 0] + dp[ m][ j][ k+1 ] \] 这里的 \(dp[ m][ j][ k+1]\) 表示在区间 \([ m, j ]\) 上,左边已经有 \(k+1\) 个同色盒子(原来的 \(k\) 个加上位置 \(i\) 的盒子),这些将在后续一起移除。 取两种选择的最大值: \[ dp[ i][ j][ k] = \max(\text{score} 1, \max {m} \text{score}_ 2) \] 算法步骤 输入数组 boxes 和 cost 函数。 预处理:对每个区间 \([ i, j ]\) 和 \(k\) 计算 dp 值。 注意 \(k\) 最大可能为 \(n\),但实际不会超过区间内同色盒子的总数,可以用记忆化搜索优化。 采用记忆化搜索实现: 如果 \(i > j\),返回 0。 如果已计算过 \(dp[ i][ j][ k ]\),直接返回。 否则,先计算选择1的得分。 然后遍历 \(m = i+1\) 到 \(j\),如果 \(boxes[ m] = boxes[ i ]\),递归计算: \[ \text{temp} = dfs(i+1, m-1, 0) + dfs(m, j, k+1) \] 更新最大值。 记录结果并返回。 最终结果 = \(dfs(0, n-1, 0)\)。 复杂度分析 状态数:\(O(n^3)\),因为 \(i, j, k\) 各 \(O(n)\)。 每个状态转移需要遍历可能的 \(m\),最坏 \(O(n)\),总复杂度 \(O(n^4)\),在 \(n \le 100\) 时可接受。 优化:可以在预处理时记录每个区间内下一个同色盒子的位置,减少枚举,但最坏情况仍然是 \(O(n^4)\)。 空间复杂度:\(O(n^3)\)。 示例演算(简略) 以 boxes = [1, 2, 1] ,cost(1)=1, cost(2)=1 为例: 计算 dp[ 0][ 2][ 0 ]: 选择1:移除 boxes[ 0] 和左边0个同色盒子,得分 = 1² - 1×1 = 0,加上 dp[ 1][ 2][ 0 ] 的结果。 选择2:找到 m=2(同色1),则 temp = dp[ 1][ 1][ 0] + dp[ 2][ 2][ 1 ]。 dp[ 1][ 1][ 0]:移除 boxes[ 1 ] 单独,得 1² - 1×1 = 0。 dp[ 2][ 2][ 1]:移除 boxes[ 2 ] 与左边1个同色盒子(共2个同色盒子),得 2² - 2×1 = 4 - 2 = 2。 所以 temp = 0 + 2 = 2。 比较:选择1需要先算 dp[ 1][ 2][ 0 ]: dp[ 1][ 2][ 0]:boxes[ 1] 与 boxes[ 2] 不同,选择1:移除 boxes[ 1] 单独,得0,加 dp[ 2][ 2][ 0 ] = 0,总0; 选择2:无同色 m,所以 dp[ 1][ 2][ 0 ] = 0。 所以选择1总分 = 0 + 0 = 0。 因此 dp[ 0][ 2][ 0 ] = max(0, 2) = 2。 最终结果 2,对应操作顺序:先移除中间的 2(得分0),剩下 [ 1,1 ] 一起移除(得分 2² - 1×2 = 2),总得分 2。 小结 本题是“移除盒子”的扩展,加入了颜色相关的移除成本。 关键点在于状态定义和转移方程的设计,特别是“左边保留的同色盒子数 k”这一维状态,使得我们可以推迟移除,以积累同色盒子获得更高的平方收益,同时减去对应的成本。