第一题:能量项链
区间型动态规划
据说这题在当年坑了很多人。
f(i, j) 表示从第i个珠子开始合并j个珠子所释放的最大能量。
f(i, j) = max{ f(i, k} + f(i+k, j-k) + head(i) * head(i+k) * head(i+j) , 0<k<j}
边界条件:f(i, 1) = 0
第二题:金明的预算方案
背包型动态规划
01背包的加强版,对于每个主件有五种选择方式:不购买主件、购买主件、购买主件和附件1、购买主件和附件2、购买主件和附件1和2。
一个显著的时空优化:将物品的价格除以10.
第三题:作业调度方案
模拟
据说原来是一道搜索题,但是为了平衡整卷难度所以简化了许多。不难,仔细就好。
第四题:2^k进制数
递推、高精度
首先想到的递推式:用 f(i, j) 表示以数字 i 开头且有 j 位的数字个数,则
f(i, j) = sum{ f(i+1, j-1), f(i+2, j-1), ... }
那么最终答案也是将某些 f 值相加。
既然我们在状态转移和求最终结果时要的都是和,不妨直接在 f 中保存之前状态的和。
所以我们可以用 f(i, j) 表示第一位不小于 i 且有 j 位的数字个数,则
f(i, j) = f(i+1, j)+f(i+1, j-1)
解释一下,第一位不小于 i 有两种情况:
1. 第一位等于 i,那么第二位至少是 i+1,即 f(i+1, j-1)
2. 第一位大于 i,即第一位大于等于 i+1,即 f(i+1, j)。
那么最终答案的求解可以分类讨论:
- 若 k | w,则答案等于 sum{ f(1, min(w/k-i, 2^k-1-i)), i∈[0, min(2^k-1, w/k)) }
解释:如果 w 能整除 k,那么枚举长度。我们知道 2^k-1 是 2^k 进制数一位上能达到的最大值,也是一个(无其他限制情况下)递增的 2^k进制数的最大位数。所以 min(w/k, 2^k-1) 就是当前情况下所能达到的最大位数。
- 若 w mod k > 0,先做完上面的步骤,然后单独统计多出来的「不完整的」一位。在这种情况下,如果存在位数为 w div k + 1 的情况,第一位可以并不能取遍 1~2^k-1,而只能取 1~2^(w mod k)-1. 将这些值累加即可。
并不是对于所有的情况都要判断该情况是否可能出现,因为有些不可能的情况的 f 值并没有计算过,是等于 0 的。比如当 k=2, w=6 时,f(1, 3) 很明显是等于 0 的,所以即使将其累加也不影响最终结果。