移除盒子(Remove Boxes)的变体:带颜色限制的移除成本问题
题目描述:
给定一行盒子,每个盒子有一种颜色(用一个正整数表示)。每次操作,你可以选择连续一段颜色相同的盒子,将它们全部移除。移除一段长度为 \(k\) 的盒子后,你会获得 \(k^2\) 分,并且剩余盒子会并拢(即原来不相邻的盒子现在可能变成相邻)。但这里有一个限制:每种颜色的盒子有一个“移除成本系数” \(c_i\)(正整数),实际获得的分数是 \(k^2 \times c_i\),其中 \(c_i\) 是该段盒子颜色的系数。目标是移除所有盒子,使获得的总分数最大。
例如,盒子颜色序列为 \([1,2,1,2,1]\),颜色 1 的成本系数为 2,颜色 2 的成本系数为 3。一种可能的操作序列:先移除中间单独的 2(长度 1,得分 \(1^2 \times 3 = 3\)),序列变成 \([1,1,2,1]\);再移除相邻的两个 1(长度 2,得分 \(2^2 \times 2 = 8\)),序列变成 \([2,1]\);接着移除 2(得分 3),最后移除 1(得分 2),总分 \(3+8+3+2=16\)。但可能存在更高得分的移除顺序。
解题思路
这是一个经典的“移除盒子”问题的变体,原题是每次移除连续同色盒子得 \(k^2\) 分(无系数)。这里增加了颜色成本系数 \(c_i\),使问题更具一般性。
核心思想仍然是区间 DP,但状态设计需要额外信息来记录区间外的同色盒子数量,因为后续合并操作可能使它们连续,从而一次性移除获得更高分。
状态定义
设盒子序列为 \(boxes[0..n-1]\),颜色种类已知,每种颜色的成本系数为 \(c[color]\)。
定义 \(dp[l][r][k]\):
- 表示子区间 \(boxes[l..r]\) 在左边已经紧邻地有 \(k\) 个与 \(boxes[l]\) 颜色相同的盒子的情况下,移除这个区间及其左边的 \(k\) 个同色盒子所能获得的最大分数。
- 注意:左边的 \(k\) 个盒子并不在区间 \([l, r]\) 内,而是我们已经假设它们存在,用于后续与区间内的同色盒子合并移除。
为什么需要 \(k\)?
因为在移除过程中,我们可能不先移除 \(boxes[l]\),而是先移除中间的其他盒子,使得 \(boxes[l]\) 和它左边的同色盒子(以及区间内后面的同色盒子)最后能连成一段一起移除,获得更高的 \((k+len)^2 \times c[color]\) 分。
状态转移
我们考虑如何从 \(dp[l][r][k]\) 转移到更小的子问题。
策略一:直接移除左边的 \(k\) 个盒子以及位置 \(l\) 的盒子(假设它们颜色相同),即一次性移除 \(k+1\) 个同色盒子,然后处理剩下的区间 \([l+1, r]\)。
\[dp[l][r][k] = \max\left(dp[l][r][k], \ (k+1)^2 \times c[color_l] + dp[l+1][r][0]\right) \]
其中 \(color_l = boxes[l]\)。这个转移对应“现在就移除”策略。
策略二:先不立即移除 \(boxes[l]\),而是寻找区间内另一个位置 \(p\)(\(l < p \le r\)),使得 \(boxes[p] = boxes[l]\)。我们将区间分成三部分:
- \([l+1, p-1]\):先独立移除这个子区间(此时左边没有额外的同色盒子,即 \(k=0\))。
- \([p, r]\):移除这个子区间时,它左边已经积累了 \(k+1\) 个同色盒子(原来的 \(k\) 个加上 \(boxes[l]\) 这个),因为 \(boxes[l]\) 还没被移除,它与 \(boxes[p]\) 颜色相同,可以后续一起移除。
因此转移为:
\[dp[l][r][k] = \max_{p: boxes[p]=boxes[l]} \left(dp[l+1][p-1][0] + dp[p][r][k+1]\right) \]
注意:当 \(l+1 > p-1\) 时,\(dp[l+1][p-1][0] = 0\)。
这个策略的关键是:推迟移除 \(boxes[l]\),让它与后面同色的 \(boxes[p]\) 以及左边积累的 \(k\) 个盒子一起移除,从而获得更高的合并得分。
边界条件
- 当 \(l > r\) 时,区间为空,\(dp[l][r][k] = 0\)。
- 当 \(l = r\) 时,区间只有一个盒子,可以立即移除:\(dp[l][r][k] = (k+1)^2 \times c[color_l]\)。
计算顺序
由于转移方程中 \(dp[l][r][k]\) 依赖于:
- \(dp[l+1][r][0]\)(更小的区间)
- \(dp[l+1][p-1][0]\)(更小的区间)
- \(dp[p][r][k+1]\)(区间长度可能相同,但 \(k\) 更大)
我们需要按照区间长度从小到大计算,同时对于同一个区间,\(k\) 要从大到小计算(因为 \(k+1\) 比 \(k\) 大)。
具体顺序:
- 枚举区间长度 \(len = 0\) 到 \(n-1\)。
- 枚举左端点 \(l = 0\) 到 \(n-len-1\),右端点 \(r = l + len\)。
- 对于每个区间 \([l, r]\),枚举 \(k\) 从 \(r-l\) 到 0(递减),因为 \(k\) 最大不会超过区间外可能积累的同色盒子数量(这里可以设为区间长度,为了简化,我们通常枚举 \(k\) 从大到小)。
最终答案
初始时,整个区间 \([0, n-1]\) 左边没有额外的同色盒子,所以 \(k=0\):
\[ans = dp[0][n-1][0] \]
举例说明
假设盒子序列:\([1,2,1,2,1]\),颜色 1 的系数 \(c[1] = 2\),颜色 2 的系数 \(c[2] = 3\)。
计算过程简述(只展示关键步骤):
-
初始化单盒子区间:
- 比如 \(dp[0][0][k] = (k+1)^2 \times 2\)(因为颜色 1)。
-
计算区间长度 2:
- 比如区间 \([0,1]\)(颜色 1,2):
- 策略一:移除第一个 1,得 \((k+1)^2 \times 2\) + \(dp[1][1][0]\)。
- 策略二:寻找后面同色 1 的位置(这里没有),所以不考虑。
- 比如区间 \([0,1]\)(颜色 1,2):
-
随着区间扩大,推迟移除同色盒子的优势显现:
- 在区间 \([0,4]\)(整个序列):
- 策略一:直接移除第一个 1(颜色 1),得 \((0+1)^2 \times 2 = 2\),然后递归处理剩余区间。
- 策略二:找到后面同色 1 的位置 p=2 和 p=4。
对于 p=2:先独立移除 \([1,1]\)(即位置 1 的颜色 2),得 \(dp[1][1][0]\);然后处理区间 \([2,4]\),此时左边已有 k+1=1 个同色 1(即位置 0 的颜色 1 还没移除),所以 \(dp[2][4][1]\) 表示在左边已有一个 1 的情况下处理区间 \([2,4]\) 的最大分。这样最后可以合并位置 0,2,4 的三个 1 一起移除,获得 \((3)^2 \times 2 = 18\) 分。
通过比较各种策略,得到最大总分为 18 + 其他操作的分数。
- 在区间 \([0,4]\)(整个序列):
最终计算可得最大总分为 24(举例数字可能不同,取决于具体系数和顺序)。
复杂度
- 状态数:\(O(n^2 \cdot n) = O(n^3)\),因为 \(k\) 最多为 \(n\)。
- 每个状态转移需要枚举 \(p\),最坏 \(O(n)\)。
- 总复杂度 \(O(n^4)\),但实际因为 \(p\) 只在同色位置枚举,可优化到 \(O(n^3)\)。
核心要点
- 状态中引入 \(k\) 表示“左边已积累的同色盒子数”,是解决此类“合并移除”问题的关键。
- 转移时考虑两种策略:立即移除 或 推迟移除(与后面同色合并)。
- 计算顺序按区间长度从小到大,\(k\) 从大到小。
这个变体在原移除盒子问题基础上增加了颜色成本系数,使得得分计算变为 \(k^2 \times c_i\),但状态设计和转移逻辑完全一致,只需在得分计算时乘上系数即可。