There are two players, A and B, in Pots of gold game, and pots of gold arranged in a line, each containing some gold coins. The players can see how many coins are there in each gold pot, and each player gets alternating turns in which the player can pick a pot from either end of the line. The winner is the player who has a higher number of coins at the end. The objective is to “maximize” the number of coins collected by A, assuming B also plays “optimally”, and A starts the game.

For example,

                      Player    Opponent
 
4, 6, 2, 3              3
4, 6, 2                            4
6, 2                    6
2                                  2
                     9 coins    6 coins
                      Player    Opponent
 
6, 1, 4, 9, 8, 5        6
1, 4, 9, 8, 5                      5
1, 4, 9, 8              8
1, 4, 9                            9
1, 4                    4
1                                  1
                     18 coins   15 coins

Practice this problem

The idea is to find an optimal strategy that makes the player wins, knowing that an opponent is playing optimally. The player has two choices for coin[i…j], where i and j denote the front and rear of the line, respectively.

 
1. If the player chooses the front pot i, the opponent is left to choose from [i+1, j].

  • If the opponent chooses front pot i+1, recur for [i+2, j].
  • If the opponent chooses rear pot j, recur for [i+1, j-1].

2. If the player chooses rear pot j, the opponent is left to choose from [i, j-1].

  • If the opponent chooses front pot i, recur for [i+1, j-1].
  • If the opponent chooses rear pot j-1, recur for [i, j-2].

 
Since the opponent is playing optimally, he will try to minimize the player’s points, i.e., the opponent will make a choice that will leave the player with minimum coins. So, we can recursively define the problem as:

                         | coin[i]                     (if i = j)
 optimalStrategy(i, j) = | max(coin[i], coin[j])       (if i + 1 = j)
                         | max (coin[i] + min(optimalStrategy(coin, i + 2, j),
                                        optimalStrategy(coin, i + 1, j – 1)),
                          coin[j] + min(optimalStrategy(coin, i + 1, j – 1),
                                           optimalStrategy(coin, i, j – 2)))

Following is the C++, Java, and Python implementation of the above approach:

C++


Download  Run Code

Output:

The maximum coins collected by the player is 9

Java


Download  Run Code

Output:

The maximum coins collected by the player is 9

Python


Download  Run Code

Output:

The maximum coins collected by the player is 9

The time complexity of the above solution is exponential and occupies space in the call stack.
 

 
The problem has optimal substructure. We have seen that the problem can be broken down into smaller subproblems, which can further be broken down into yet smaller subproblems, and so on. The problem also exhibits overlapping subproblems, so we will end up solving the same subproblem over and over again. We know that problems with optimal substructure and overlapping subproblems can be solved by dynamic programming, where subproblem solutions are memoized rather than computed and again.

Following is the C++, Java, and Python program that demonstrates it:

C++


Download  Run Code

Output:

The maximum coins collected by the player is 9

Java


Download  Run Code

Output:

The maximum coins collected by the player is 9

Python


Download  Run Code

Output:

The maximum coins collected by the player is 9

The time complexity of the above top-down solution is O(n2) and requires O(n2) extra space, where n is the total number of gold pots.

 
Following is a bottom-up version of the above approach in C++, Java, and Python:

C++


Download  Run Code

Output:

The maximum coins collected by the player is 9

Java


Download  Run Code

Output:

The maximum coins collected by the player is 9

Python


Download  Run Code

Output:

The maximum coins collected by the player is 9

The time complexity of the above bottom-up solution is O(n2) and requires O(n) extra space, where n is the total number of gold pots.