Stone Game
Note the problem description in LintCode is different from LeetCode for "Stone Game". Here we discuss the LintCode version:
https://www.lintcode.com/problem/stone-game/description
Question
There is a stone game.At the beginning of the game the player picks n piles of stones in a line.
The goal is to merge the stones in one pile observing the following rules:
At each step of the game, the player can merge two adjacent piles to a new pile.
The score is the number of stones in the new pile.
You are to determine the minimum of the total score.
Example
For [4, 1, 1, 4], in the best solution, the total score is 18:
1. Merge second and third piles => [4, 2, 4], score +2
2. Merge the first two piles => [6, 4],score +6
3. Merge the last two piles => [10], score +10Other two examples:
[1, 1, 1, 1] return 8
[4, 4, 5, 9] return 43
Tags
Dynamic Programming
Related Problems
Hard Burst Balloons 29 %
Analysis
死胡同:容易想到的一个思路从小往大,枚举第一次合并是在哪?
转而用记忆化搜索的思路,从大到小,先考虑最后的0 ~ n-1合并的总花费。
Dynamic Programming
DP四要素
State:
dp[i][j]表示把第i到第j个石子合并到一起的最小花费
Function:
预处理
sum[i,j]表示i到j所有石子价值和dp[i][j] = min(dp[i][k]+dp[k+1][j]+sum[i,j])对于所有k属于{i,j}
Intialize:
for each i
dp[i][i] = 0
Answer:
dp[0][n-1]
区间型DP,利用二维数组下标表示下标范围。 需要注意的是对状态转移方程的理解,也就是对每一种分割方式进行遍历.
Divide & Conquer + Memoization
分割成子问题的思路在于用不同的pivot将原有的数组分割成为不同的区间,并且递归地每一个子区间重复同样的分割过程。
计算interval sum时,已知start和end,那么最好的方式就是预先生成一个prefix sum数组,这样区间和就可以用sum[end + 1] - sum[start + 1 - 1]来计算.
对于 interval sum ,根据搜索结构可以做一个显而易见的优化,因为每次 split 的 start, pivot, end 我们都知道,而且合并(start, end) 区间的两堆石子,最终的区间和一定为 (start, end) 的区间和,用一维的 prefix sum 数组就可以了。
用 prefix sum 数组要记得初始化时候的 int[n + 1] zero padding,还有取值时候对应的 sum[end + 1] - sum[start + 1 - 1] offset.
每次归并的 cost = 归并两个区间的最优 cost + 两个区间的区间和,即:
比较要注意的是循环pivot时数组的下标,以下两种实现方式都是可行的 (注意防止出现无限循环,即recursive调用搜索函数时,不能出现start, end又被当成输入的情况):
i ~ [start, end - 1], => [start, i], [i + 1, end - 1]
i ~ [start + 1, ... end], => [start, i - 1], [i, end]
Solution
DP - (252 ms)
(Preferred) Divide and Conquer + Memoization (251 ms AC)
Reference
Last updated
Was this helpful?