题目大意
有 $n$ 张牌,写有数字 $a_1,\cdots,a_n$。
每一轮操作,选择连续的三张牌,吃掉中间那张,然后把中间那张的数字加到其余两张上。
直到只剩两张牌为止。
目标是使得最后剩下的两张牌的数字和最小,输出最小的和。
$2 \leq n \leq 18,~0 \leq a_i \leq 10^9$
时限 2s
题解
最近 atcoder 的模型怎么都这么。。。
要考虑每张牌的贡献,实际上就是想要知道每张牌被算了多少次。
然后发现算这个贼麻烦,它对左右都有贡献,还跟顺序有关。。。
所以题解又给了个好办法。
一开始,最左和最右这两张牌都是贡献 $1$ 次的。
对于当前区间 $[l,r]$,枚举最后被吃掉的是哪张牌,假设是 $i$,那么 $i$ 这张牌的贡献次数就是 $l$ 的次数加上 $r$ 的次数。
设 $f_{l,r,x,y}$ 表示当前 $[l,r]$ 这个区间,$l$ 被贡献了 $x$ 次,$r$ 被贡献了 $y$ 次,所能达到的最小代价和。于是就枚举 $i$ 然后 dp 下去了。
分析一波复杂度。首先是状态数,$l,r$ 总共是 $O(n^2)$,至于 $x,y$,它与 dp 时选择哪个 $i$ 无关,每往下走一层会产生两种新的状态,因此总量是 $O(2^n)$ 的。因此状态数是 $O(2^nn^2)$ 的,加上转移后时间就是 $O(2^nn^3)$ 跑不满。
用记忆化搜索实现,代码贼短。
代码
1 |
|