Program to find maximum score in stone game in Python

Suppose there are several stones placed in a row, and each of these stones has an associated number which is given in an array stoneValue. In each round Amal divides the row into two parts then Bimal calculates the value of each part which is the sum of the values of all the stones in this part. Bimal throws away the part which has the maximum value, and Amal's score increases by the value of the remaining part. When the values of two parts are same, Bimal lets Amal decide which part will be thrown away. The next round starts with the remaining part. The game ends when there is only one stone remaining. We have to find the maximum score that Amal can get.

So, if the input is like stoneValue = [7,3,4,5,6,6], then the output will be

  • At round 1, Amal divides the row like [7,3,4], [5,6,6]. Sum of left row is 14 and sum of right row is 17. Bimal throws away the right row and Amal's score is now 14.

  • At round 2, Amal divides the row to [7], [3,4]. So Bimal throws away the left row and Amal's score becomes (14 + 7) = 21.

  • At round 3, Amal has only one choice to divide the row which is [3], [4]. Bimal throws away the right row and Amal's score is now (21 + 3) = 24.

To solve this, we will follow these steps −

  • Define a function dfs() . This will take start, end

  • if start >= end, then

    • return 0

  • max_score := 0

  • for cut in range start to end, do

    • sum1 := partial_sum[start, cut]

    • sum2 := partial_sum[cut+1, end]

    • if sum1 > sum2 , then

      • score := sum2 + dfs(cut+1, end)

    • otherwise when sum1 < sum2, then

      • score := sum1 + dfs(start, cut)

    • otherwise,

      • score := sum1 + maximum of dfs(start, cut) and dfs(cut+1, end)

    • max_score := maximum of score and max_score

  • return max_score

  • Define a function getPartialSum() . This will take

  • for i in range 0 to n - 1, do

    • partial_sum[i, i] := stoneValue[i]

  • for i in range 0 to n - 1, do

    • for j in range i+1 to n - 1, do

      • partial_sum[i, j] := partial_sum[i, j-1] + stoneValue[j]

  • From the main method, do the following

  • n := size of stoneValue

  • partial_sum := A square array of size n x n and filled with 0

  • getPartialSum()

  • return dfs(0, n-1)


Let us see the following implementation to get better understanding

def solve(stoneValue):
   def dfs(start, end):
      if start >= end:
         return 0
      max_score = 0

      for cut in range(start, end):
         sum1 = partial_sum[start][cut]
         sum2 = partial_sum[cut+1][end]
         if sum1 > sum2:
            score = sum2+dfs(cut+1, end)
         elif sum1 < sum2:
            score = sum1+dfs(start, cut)
            score = sum1+max(dfs(start, cut), dfs(cut+1, end))
            max_score = max(score, max_score)
      return max_score

   def getPartialSum():
      for i in range(n):
         partial_sum[i][i] = stoneValue[i]
      for i in range(n):
         for j in range(i+1, n):
            partial_sum[i][j] = partial_sum[i][j-1]+stoneValue[j]

   n = len(stoneValue)
   partial_sum = [[0]*n for _ in range(n)]
   return dfs(0, n-1)

stoneValue = [7,3,4,5,6,6]