题目:http://acm.jlu.edu.cn/joj/showproblem.php?pid=1109
大意就是有L个使用频率各不相同的字符,把它们按顺序分配到K个按键上,使总代价最小,代价定义为一个字母的使用频率乘以它被分配到某个按键上的位置(一个字母的位置要么是1,表示它被安排成为某个键的首字母,或者是它前面的字母的位置加1,表示它与它前面的字母分配到同一个按键上)。这个题目最直接的想法就是在L个字母中找出K个,把它们分配到K个按键的第一个位置,或者说就是L个元素分成K段使总代价最小。
L取K的问题是有组合公式的:C(L,K) = C(L-1, K-1) + C(L-1, K)。这是个递推公式,递推公式本身就有动态规划的性质。这个递推公式的组合意义是:L中取K,考察某个具体的元素E,要么取出的K个中有E,则问题等价于从剩下的L-1个中取K-1个,要么取出的K个中没有E,问题就等价于从剩下的L-1个中取K个。这个分析过程可以完全照搬到这个题目中。
定义f(L,K)表示前L个字母分配到K个按键的子问题的最优代价,cost(i, j)表示第i个字母到第j个字母被分配到一个按键上的代价。f(L,K)对应的分配的方案是这样的:要么第L个字母单独被分配到一个按键上,此时代价就是f(L-1,K-1) + cost(L, L),要么第L个字母与前面的字母一起被分配到第K个按键上,此时代价就是f(i, K-1) + cost(i+1, L),其中K-1 <= i < L-1,f(L,K)就是这两个代价的最小值。注意到第二种情况中,当i = L-1时,它的公式就是第一种情况的公式,所以最终问题统一起来:
f(L, K) = min { f(i, K-1) + cost(i+1, L) }, K-1 <= i <= L-1
边界情况:f(i, 1) = cost(1, i), f(i, i) = cost(1, 1) + cost(2, 2) + … + cost(i, i), f(i, j) = inf 当i < j。
计算cost函数:cost(i, i) = freq[i], cost(i, j) = cost(i, j – 1) + freq[j] * (j – i + 1)。
根据最优代价重新构造出一个分配方案也很简单,定义s(L, K)表示前L个字母分配到K个按键上最后一个按键的划分位置,pos[p]表示第p个按键的划分位置,重构分配方案:
for(i = L, j = K; j >= 1; j--) {
pos[j] = s[i][j];
i = s[i][j] - 1;
}
感觉这个问题还可以使用矩阵链乘法的动态规划思路。