GFG App
Open App
Browser
Continue

Maximize the number of coins collected by X, assuming Y also plays optimally

Two players X and Y are playing a game in which there are pots of gold arranged in a line, each containing some gold coins. They get alternating turns in which the player can pick a pot from one of the ends 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 X, assuming Y also plays optimally. Return the maximum coins X could get while playing the game. Initially, X starts the game.

Examples:

Input: N = 4, Q[] = {8, 15, 3, 7}
Output: 22
Explanation: Player X starts and picks 7. Player Y picks the pot containing 8. Player X picks the pot containing 15. Player Y picks 3. Total coins collected by X = 7 + 15 = 22.

Input:N = 4, A[] = {2, 2, 2, 2}
Output: 4

Approach: This can be solved with the following idea:

Using Dynamic programming as it has an optimum substructure and overlapping subproblems.

Steps involved in the implementation of code:

• Declare a static 1002 x 1002 2D integer array with the name dp.
• Add a public static method called “getMaxCoins” that accepts an integer array called “coins, ” together with the parameters “integer start” and “integer end, ” and returns an integer result.
• Return zero if start exceeds finish.
• Return dp[start][end] if dp[start][end] is not equal to -1.
• Create the variables option1 and option2 as two integers.
• GetMaxCoins with parameters coins, start+1, end-1, and getMaxCoins with parameters coins, start, end-2 are called recursively with the option1 set to coins[end] plus the minimum value in between.
• Option 2 should be set to coins[start] plus the minimum value in between calls to the recursive functions getMaxCoins with the arguments coins, start+2, end, and getMaxCoins with the arguments coins, start+1, end-1.
• Set the highest value possible between options 1 and 2 for dp[start][end].
• Bring back dp[start][end].
• Make a public static method called maxCoins that receives an integer value as a return parameter and accepts integer array coins and an integer n as input arguments.
• To add -1 values to the dp array, use a nested loop.
• Return the value of the getMaxCoins method with parameters coins, 0, n-1

Below is the code implementation of the above approach:

C++14

 `// C++ code of the above approach` `#include ` `using` `namespace` `std;`   `int` `dp[1002][1002];`   `// Returns the maximum coins that` `// can be collected from start to end` `int` `getMaxCoins(``int` `coins[], ``int` `start, ``int` `end)` `{` `    ``// Base case: When start index is` `    ``// greater than end index` `    ``if` `(start > end) {` `        ``return` `0;` `    ``}`   `    ``// If we have already computed the` `    ``// solution for this sub-problem` `    ``if` `(dp[start][end] != -1) {` `        ``return` `dp[start][end];` `    ``}`   `    ``// Case 1: Choose the last coin,` `    ``// then we can choose between the` `    ``// first and second-last coins` `    ``int` `option1` `        ``= coins[end]` `          ``+ min(getMaxCoins(coins, start + 1, end - 1),` `                ``getMaxCoins(coins, start, end - 2));`   `    ``// Case 2: Choose the first coin,` `    ``// then we can choose between the` `    ``// second and last coins` `    ``int` `option2` `        ``= coins[start]` `          ``+ min(getMaxCoins(coins, start + 2, end),` `                ``getMaxCoins(coins, start + 1, end - 1));`   `    ``// Store the maximum coins that` `    ``// can be collected from start` `    ``// to end` `    ``dp[start][end] = max(option1, option2);`   `    ``return` `dp[start][end];` `}`   `int` `maxCoins(``int` `coins[], ``int` `n)` `{` `    ``// Initialize the DP array with -1` `    ``memset``(dp, -1, ``sizeof``(dp));`   `    ``return` `getMaxCoins(coins, 0, n - 1);` `}`   `// Driver code` `int` `main()` `{` `    ``int` `coins[] = { 8, 15, 3, 7 };` `    ``int` `n = ``sizeof``(coins) / ``sizeof``(coins[0]);` `    ``int` `maxCoin = maxCoins(coins, n);`   `    ``// Function call` `    ``cout << maxCoin << endl;`   `    ``return` `0;` `}`

Java

 `// Java code of the above approach` `import` `java.util.*;`   `class` `GfG {` `    ``public` `static` `int` `dp[][] = ``new` `int``[``1002``][``1002``];`   `    ``// Returns the maximum coins that` `    ``// can be collected from start to end` `    ``public` `static` `int` `getMaxCoins(``int``[] coins, ``int` `start,` `                                  ``int` `end)` `    ``{`   `        ``// Base case: When start index is` `        ``// greater than end index` `        ``if` `(start > end) {` `            ``return` `0``;` `        ``}`   `        ``// If we have already computed the` `        ``// solution for this sub-problem` `        ``if` `(dp[start][end] != -``1``) {` `            ``return` `dp[start][end];` `        ``}`   `        ``// Case 1: Choose the last coin,` `        ``// then we can choose between the` `        ``// first and second-last coins` `        ``int` `option1` `            ``= coins[end]` `              ``+ Math.min(` `                    ``getMaxCoins(coins, start + ``1``, end - ``1``),` `                    ``getMaxCoins(coins, start, end - ``2``));`   `        ``// Case 2: Choose the first coin,` `        ``// then we can choose between the` `        ``// second and last coins` `        ``int` `option2` `            ``= coins[start]` `              ``+ Math.min(` `                    ``getMaxCoins(coins, start + ``2``, end),` `                    ``getMaxCoins(coins, start + ``1``, end - ``1``));`   `        ``// Store the maximum coins that` `        ``// can be collected from start` `        ``// to end` `        ``dp[start][end] = Math.max(option1, option2);`   `        ``return` `dp[start][end];` `    ``}`   `    ``public` `static` `int` `maxCoins(``int``[] coins, ``int` `n)` `    ``{`   `        ``// Initialize the DP array with -1` `        ``for` `(``int` `i = ``0``; i < ``1001``; i++) {` `            ``Arrays.fill(dp[i], -``1``);` `        ``}`   `        ``return` `getMaxCoins(coins, ``0``, n - ``1``);` `    ``}`   `    ``// Driver code` `    ``public` `static` `void` `main(String args[])` `    ``{` `        ``int``[] coins = { ``8``, ``15``, ``3``, ``7` `};` `        ``int` `n = coins.length;` `        ``int` `maxCoins = maxCoins(coins, n);`   `        ``// Function call` `        ``System.out.println(maxCoins);` `    ``}` `}`

Python3

 `class` `GfG:` `    ``dp ``=` `[[``-``1` `for` `i ``in` `range``(``1002``)] ``for` `j ``in` `range``(``1002``)]`   `    ``# Returns the maximum coins that` `    ``# can be collected from start to end` `    ``def` `getMaxCoins(``self``, coins, start, end):` `        ``# Base case: When start index is` `        ``# greater than end index` `        ``if` `start > end:` `            ``return` `0`   `        ``# If we have already computed the` `        ``# solution for this sub-problem` `        ``if` `self``.dp[start][end] !``=` `-``1``:` `            ``return` `self``.dp[start][end]`   `        ``# Case 1: Choose the last coin,` `        ``# then we can choose between the` `        ``# first and second-last coins` `        ``option1 ``=` `coins[end] ``+` `min``(``self``.getMaxCoins(coins, start ``+` `1``, end ``-` `1``), ``self``.getMaxCoins(coins, start, end ``-` `2``))`   `        ``# Case 2: Choose the first coin,` `        ``# then we can choose between the` `        ``# second and last coins` `        ``option2 ``=` `coins[start] ``+` `min``(``self``.getMaxCoins(coins, start ``+` `2``, end), ``self``.getMaxCoins(coins, start ``+` `1``, end ``-` `1``))`   `        ``# Store the maximum coins that` `        ``# can be collected from start` `        ``# to end` `        ``self``.dp[start][end] ``=` `max``(option1, option2)`   `        ``return` `self``.dp[start][end]`   `    ``def` `maxCoins(``self``, coins, n):` `        ``# Initialize the DP array with -1` `        ``for` `i ``in` `range``(``1001``):` `            ``for` `j ``in` `range``(``1001``):` `                ``self``.dp[i][j] ``=` `-``1`   `        ``return` `self``.getMaxCoins(coins, ``0``, n ``-` `1``)`   `# Driver code` `if` `__name__ ``=``=` `'__main__'``:` `    ``coins ``=` `[``8``, ``15``, ``3``, ``7``]` `    ``n ``=` `len``(coins)` `    ``gfg ``=` `GfG()` `    ``maxCoins ``=` `gfg.maxCoins(coins, n)`   `    ``# Function call` `    ``print``(maxCoins)`

C#

 `using` `System;`   `class` `GFG {` `    ``public` `static` `int``[,] dp = ``new` `int``[1002, 1002];`   `    ``// Returns the maximum coins that can be collected from start to end` `    ``public` `static` `int` `getMaxCoins(``int``[] coins, ``int` `start, ``int` `end) {` `        ``// Base case: When start index is greater than end index` `        ``if` `(start > end) {` `            ``return` `0;` `        ``}`   `        ``// If we have already computed the solution for this sub-problem` `        ``if` `(dp[start, end] != -1) {` `            ``return` `dp[start, end];` `        ``}`   `        ``// Case 1: Choose the last coin, then we can choose ` `       ``// between the first and second-last coins` `        ``int` `option1 = ` `          ``coins[end] + Math.Min(getMaxCoins(coins, start + 1, end - 1), ` `                                ``getMaxCoins(coins, start, end - 2));`   `        ``// Case 2: Choose the first coin, ` `       ``// then we can choose between the second and last coins` `        ``int` `option2 = ` `          ``coins[start] + Math.Min(getMaxCoins(coins, start + 2, end), ` `                                  ``getMaxCoins(coins, start + 1, end - 1));`   `        ``// Store the maximum coins that can be collected from start to end` `        ``dp[start, end] = Math.Max(option1, option2);`   `        ``return` `dp[start, end];` `    ``}`   `    ``public` `static` `int` `maxCoins(``int``[] coins, ``int` `n) {` `        ``// Initialize the DP array with -1` `        ``for` `(``int` `i = 0; i < 1001; i++) {` `            ``for` `(``int` `j = 0; j < 1001; j++) {` `                ``dp[i,j] = -1;` `            ``}` `        ``}`   `        ``return` `getMaxCoins(coins, 0, n - 1);` `    ``}`   `    ``// Driver code` `    ``public` `static` `void` `Main() {` `        ``int``[] coins = {8, 15, 3, 7};` `        ``int` `n = coins.Length;` `        ``int` `mxCoins = maxCoins(coins, n);`   `        ``// Function call` `        ``Console.WriteLine(mxCoins);` `    ``}` `}`

Javascript

 `// JavaScript code of the above approach`   `// Returns the maximum coins that` `// can be collected from start to end` `function` `getMaxCoins(coins, start, end, dp) {` `    `  `    ``// Base case: When start index is` `    ``// greater than end index` `    ``if` `(start > end) {` `        ``return` `0;` `    ``}`   `    ``// If we have already computed the` `    ``// solution for this sub-problem` `    ``if` `(dp[start][end] != -1) {` `        ``return` `dp[start][end];` `    ``}`   `    ``// Case 1: Choose the last coin,` `    ``// then we can choose between the` `    ``// first and second-last coins` `    ``let option1 =` `        ``coins[end]` `        ``+ Math.min(getMaxCoins(coins, start + 1, end - 1, dp),` `                    ``getMaxCoins(coins, start, end - 2, dp));`   `    ``// Case 2: Choose the first coin,` `    ``// then we can choose between the` `    ``// second and last coins` `    ``let option2 =` `        ``coins[start]` `        ``+ Math.min(getMaxCoins(coins, start + 2, end, dp),` `                    ``getMaxCoins(coins, start + 1, end - 1, dp));`   `    ``// Store the maximum coins that` `    ``// can be collected from start` `    ``// to end` `    ``dp[start][end] = Math.max(option1, option2);`   `    ``return` `dp[start][end];` `}`   `function` `maxCoins(coins, n) {` `    ``let dp = [];`   `    ``// Initialize the DP array with -1` `    ``for` `(let i = 0; i <= n; i++) {` `        ``dp[i] = Array(n).fill(-1);` `    ``}`   `    ``return` `getMaxCoins(coins, 0, n - 1, dp);` `}`   `// Driver code` `let coins = [ 8, 15, 3, 7 ];` `let n = coins.length;` `let maxCoin = maxCoins(coins, n);`   `// Function call` `console.log(maxCoin);` `// This code is contributed by prasad264`

Output

`22`

Time Complexity: O(N2)
Auxiliary Space: O(N2)

My Personal Notes arrow_drop_up