Stone Game

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:

  1. At each step of the game,the player can merge two adjacent piles to a new pile.
  2. The score is the number of stones in the new pile.

You are to determine the minimum of the total score.

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 +10

Other two examples:
[1, 1, 1, 1] return 8
[4, 4, 5, 9] return 43

这是一道比较典型的区间类DP题目.如果从小到大合并,则这题很难选择.一个比较好的方式是自顶向下,先考虑最后一次合并的费用.每一次合并的附加费用是合并的两堆石块的总数目,即新石堆的石块数目.

我们可以枚举合并的位置,看哪个位置的成本最小,这个过程可以一直进行下去,直到一个石块的时候,合并成本是0.这中间因为枚举分割位,有非常多的重复区间.所以需要判断是否已经处理过. f的DP矩阵一开始初始化为-1,如果某个位置不是-1,则说明已经处理过,不必另外维护一个visited矩阵,另外,每次我们都要求区间和,也是一个重复性非常高的过程,可以提前求出.一个是直接求各个区间点的值,是二维矩阵,另外一个是先求前缀和数组,利用这个数组求区间和.显然后者空间复杂度低很多.代码如下:

class Solution:
    # @param {int[]} A an integer array
    # @return {int} an integer
    def stoneGame(self, A):
        # memory search 
        if not A:
            return 0
        f = [[-1]*len(A) for i in xrange(len(A))]
        for i in xrange(len(A)):
            f[i][i] = 0
        cost = [0]*(len(A)+1)
        for i in xrange(1, len(A)+1):
            cost[i] = cost[i-1] + A[i-1]
        return self.search(A, f, cost, 0, len(A) - 1 )
        
    def search(self, A, f, cost, start, end):
        if f[start][end] >= 0:
            return f[start][end]
        import sys    
        f[start][end] = sys.maxint
        for k in xrange(start,end):
           left = self.search(A, f, cost, start, k)
           right = self.search(A, f, cost,  k+1, end)
           f[start][end] = min(f[start][end], left + right + cost[end+1] - cost[start])
        
        return f[start][end]

时间复杂度为O(n^3),枚举两边和切分位置.空间复杂度为O(n^2),DP矩阵。

这题有贪心做法,其实相当于霍夫曼编码,每次取最小的两堆做合并(包括新生成的堆)。这么做有可以用好几种思路,一种是排序,但是需要动态增加数字,堆是一种合理的做法。可以动态增删,另外也可以使用单调队列。具体见http://www.cnblogs.com/neverforget/archive/2011/10/13/ll.html 里面合并果子这一题。

转载于:https://www.cnblogs.com/sherylwang/p/5608013.html

发布了130 篇原创文章 · 获赞 55 · 访问量 20万+
展开阅读全文
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览