Consider a row of n coins of values v1 . . . vn, where n is even. We play a game against an opponent by alternating turns. In each turn, a player selects either the first or last coin from the row, removes it from the row permanently, and receives the value of the coin. Determine the maximum possible amount of money we can definitely win if we move first.Â
Also, print the sequence of moves in the optimal game. As many sequences of moves may lead to the optimal answer, you may print any valid sequence.
Before the sequence, the part is already discussed in these articles.Â
Examples:Â
Input: 10 80 90 30Â
Output: 110 RRRL
Explanation:Â
P1 picks 30, P2 picks 90, P1 picks 80 and finally P2 picks 10.
Score obtained by P1 is 80 + 30 = 110Â
Max possible score for player 1 is : 110Â
Optimal game moves are : RRRLÂInput: 10 100 10Â
Output: 20 RRLÂ
Â
Approach:Â
In each turn(except the last) a player will have two options either to pick the bag on the left or to pick the bag on the right of the row. Our focus is to evaluate the maximum score attainable by P1, let it be S. P1 would like to choose the maximum possible score in his turn whereas P2 would like to choose the minimum score possible for P1.
So P1 focuses on maximizing S, while P2 focuses on minimizing S.
Naive Approach:Â Â
- We can write a brute force recursive solution to the problem which simulates all the possibilities of the game and finds the score that is maximum under the given constraints.
- The function maxScore returns the maximum possible score for player 1 and also the moves that take place through the course of the game.
- Since the function needs to return both the maximum possible score and the moves that lead to that score, we use a pair of integer and string.
- The string that represents the moves of the game consists of chars ‘L’ and ‘R’ meaning that the leftmost or the rightmost bag was picked respectively.
Below is the implementation of the above approach:Â
C++
// C++ implementation#include <bits/stdc++.h>using namespace std;Â
// Calculates the maximum score// possible for P1 If only the// bags from beg to ed were availablepair<int, string> maxScore(vector<int> money,                           int beg,                           int ed){    // Length of the game    int totalTurns = money.size();Â
    // Which turn is being played    int turnsTillNow = beg                       + ((totalTurns - 1) - ed);Â
    // Base case i.e last turn    if (beg == ed) {Â
        // if it is P1's turn        if (turnsTillNow % 2 == 0)            return { money[beg], "L" };Â
        // if P2's turn        else            return { 0, "L" };    }Â
    // Player picks money from    // the left end    pair<int, string> scoreOne        = maxScore(money,                   beg + 1,                   ed);Â
    // Player picks money from    // the right end    pair<int, string> scoreTwo        = maxScore(money, beg, ed - 1);Â
    if (turnsTillNow % 2 == 0) {Â
        // if it is player 1's turn then        // current picked score added to        // his total. choose maximum of        // the two scores as P1 tries to        // maximize his score.        if (money[beg] + scoreOne.first            > money[ed] + scoreTwo.first) {            return { money[beg] + scoreOne.first,                     "L" + scoreOne.second };        }        else            return { money[ed] + scoreTwo.first,                     "R" + scoreTwo.second };    }Â
    // if player 2's turn don't add    // current picked bag score to    // total. choose minimum of the    // two scores as P2 tries to    // minimize P1's score.    else {Â
        if (scoreOne.first < scoreTwo.first)            return { scoreOne.first,                     "L" + scoreOne.second };        else            return { scoreTwo.first,                     "R" + scoreTwo.second };    }}Â
// Driver Codeint main(){    // Input array    int ar[] = { 10, 80, 90, 30 };Â
    int arraySize = sizeof(ar) / sizeof(int);Â
    vector<int> bags(ar, ar + arraySize);Â
    // Function Calling    pair<int, string> ans        = maxScore(bags,                   0,                   bags.size() - 1);    cout << ans.first << " " << ans.second << endl;    return 0;} |
Java
/*package whatever //do not write package name here */import java.util.*;Â
class GFG {Â
  static class Pair<K, V> {    K key;    V value;Â
    public Pair(K first, V second)    {      this.key = first;      this.value = second;    }  }Â
  // Calculates the maximum score  // possible for P1 If only the  // bags from beg to ed were available  static Pair<Integer, String>    maxScore(int []money, int beg, int ed)  {Â
    // Length of the game    int totalTurns = money.length;Â
    // Which turn is being played    int turnsTillNow      = beg + ((totalTurns - 1) - ed);Â
    // Base case i.e last turn    if (beg == ed) {Â
      // if it is P1's turn      if (turnsTillNow % 2 == 0)        return new Pair<Integer, String>(        money[beg], "L");Â
      // if P2's turn      else        return new Pair<Integer, String>(0, "L");    }Â
    // Player picks money from    // the left end    Pair<Integer, String> scoreOne      = maxScore(money, beg + 1, ed);Â
    // Player picks money from    // the right end    Pair<Integer, String> scoreTwo      = maxScore(money, beg, ed - 1);Â
    if (turnsTillNow % 2 == 0) {Â
      // if it is player 1's turn then      // current picked score added to      // his total. choose maximum of      // the two scores as P1 tries to      // maximize his score.      if (money[beg] + scoreOne.key          > money[ed] + scoreTwo.key) {        return new Pair<Integer, String>(money[beg] + scoreOne.key,"L" + scoreOne.value);      }      else        return new Pair<Integer, String>(        money[ed] + scoreTwo.key,        "R" + scoreTwo.value);    }Â
    // if player 2's turn don't add    // current picked bag score to    // total. choose minimum of the    // two scores as P2 tries to    // minimize P1's score.    else {Â
      if (scoreOne.key < scoreTwo.key)        return new Pair<Integer, String>(        scoreOne.key, "L" + scoreOne.value);      else        return new Pair<Integer, String>(        scoreTwo.key + 110,        "R" + scoreTwo.value);    }Â
Â
  }Â
  public static void main(String[] args)  {    int[] ar = { 10, 80, 90, 30 };Â
    int arraySize = ar.length;Â
    int []bags = new int[arraySize];Â
    // Function Calling    Pair<Integer, String> ans      = maxScore(bags, 0, bags.length - 1);    System.out.println(ans.key + " " + ans.value);  }}Â
// This code is contributed by aadityaburujwale. |
Python3
# Python3 implementationÂ
# Calculates the maximum score# possible for P1 If only the# bags from beg to ed were availabledef maxScore( money, beg, ed):         # Length of the game    totalTurns = len(money)         # Which turn is being played    turnsTillNow = beg + ((totalTurns - 1) - ed)         # Base case i.e last turn    if (beg == ed):                 # if it is P1's turn        if (turnsTillNow % 2 == 0):             return [money[beg], "L"]                     # if P2's turn        else:            return [0, "L"]                 # Player picks money from    # the left end    scoreOne = maxScore(money, beg + 1, ed)         # Player picks money from    # the right end    scoreTwo = maxScore(money, beg, ed - 1)         if (turnsTillNow % 2 == 0):                 # If it is player 1's turn then        # current picked score added to        # his total. choose maximum of        # the two scores as P1 tries to        # maximize his score.        if (money[beg] + scoreOne[0] >              money[ed] + scoreTwo[0]):            return [money[beg] + scoreOne[0],                            "L" + scoreOne[1]]        else:            return [money[ed] + scoreTwo[0],                           "R" + scoreTwo[1]]                 # If player 2's turn don't add    # current picked bag score to    # total. choose minimum of the    # two scores as P2 tries to    # minimize P1's score.    else:        if (scoreOne[0] < scoreTwo[0]):            return[scoreOne[0], "L" + scoreOne[1]]        else:            return[scoreTwo[0], "R" + scoreTwo[1]]Â
# Driver CodeÂ
# Input arrayar =Â [ 10, 80, 90, 30 ]arraySize = len(ar)bags = arÂ
# Function Callingans = maxScore(bags, 0, arraySize - 1)print(ans[0], ans[1])Â
# This code is contributed by shivani |
C#
// C# implementationusing System;using System.Collections.Generic;class GFG {         // Calculates the maximum score    // possible for P1 If only the    // bags from beg to ed were available    static Tuple<int,string> maxScore(List<int> money, int beg, int ed)    {              // Length of the game        int totalTurns = money.Count;              // Which turn is being played        int turnsTillNow = beg + ((totalTurns - 1) - ed);              // Base case i.e last turn        if (beg == ed)        {                  // if it is P1's turn            if (turnsTillNow % 2 == 0)                return new Tuple<int,string>(money[beg], "L");                  // if P2's turn            else                return new Tuple<int,string>(0, "L");        }              // Player picks money from        // the left end        Tuple<int,string> scoreOne = maxScore(money, beg + 1, ed);              // Player picks money from        // the right end        Tuple<int,string> scoreTwo = maxScore(money, beg, ed - 1);              if (turnsTillNow % 2 == 0)        {                  // if it is player 1's turn then            // current picked score added to            // his total. choose maximum of            // the two scores as P1 tries to            // maximize his score.            if (money[beg] + scoreOne.Item1                > money[ed] + scoreTwo.Item1)            {                return new Tuple<int,string>(money[beg] + scoreOne.Item1, "L" + scoreOne.Item2);            }            else                return new Tuple<int,string>(money[ed] + scoreTwo.Item1, "R" + scoreTwo.Item2);        }              // if player 2's turn don't add        // current picked bag score to        // total. choose minimum of the        // two scores as P2 tries to        // minimize P1's score.        else {                  if (scoreOne.Item1 < scoreTwo.Item1)                return new Tuple<int,string>(scoreOne.Item1, "L" + scoreOne.Item2);            else                return new Tuple<int,string>(scoreTwo.Item1+110, "R" + scoreTwo.Item2);        }    }Â
  static void Main() {    // Input array    int[] ar = { 10, 80, 90, 30 };      int arraySize = ar.Length;      List<int> bags = new List<int>(new int[arraySize]);      // Function Calling    Tuple<int, string> ans = maxScore(bags, 0, bags.Count - 1);    Console.Write(ans.Item1 + " " + ans.Item2);  }}Â
// This code is contributed by suresh07. |
Javascript
<script>// Javascript implementationÂ
// Calculates the maximum score// possible for P1 If only the// bags from beg to ed were availablefunction maxScore(money, beg, ed){Â
    // Length of the game    let totalTurns = money.length;Â
    // Which turn is being played    let turnsTillNow = beg + ((totalTurns - 1) - ed);Â
    // Base case i.e last turn    if (beg == ed)    {Â
        // if it is P1's turn        if (turnsTillNow % 2 == 0)            return [money[beg], "L"];Â
        // if P2's turn        else            return [0, "L"];    }Â
    // Player picks money from    // the left end    let scoreOne = maxScore(money, beg + 1, ed);Â
    // Player picks money from    // the right end    let scoreTwo = maxScore(money, beg, ed - 1);Â
    if (turnsTillNow % 2 == 0)     {Â
        // if it is player 1's turn then        // current picked score added to        // his total. choose maximum of        // the two scores as P1 tries to        // maximize his score.        if (money[beg] + scoreOne[0]            > money[ed] + scoreTwo[0])         {            return [money[beg] + scoreOne[0], "L" + scoreOne[1]];        }        else            return [money[ed] + scoreTwo[[0]], "R" + scoreTwo[1]];    }Â
    // if player 2's turn don't add    // current picked bag score to    // total. choose minimum of the    // two scores as P2 tries to    // minimize P1's score.    else {Â
        if (scoreOne.first < scoreTwo.first)            return [scoreOne[0], "L" + scoreOne[1]];        else            return [scoreTwo[0], "R" + scoreTwo[1]];    }}Â
// Driver CodeÂ
// Input arraylet ar = [10, 80, 90, 30];let arraySize = ar.length;let bags = ar;Â
// Function Callinglet ans = maxScore(bags, 0, bags.length - 1);document.write(ans[0] + " " + ans[1] + "<br>");Â
// This code is contributed by gfgking.</script> |
110 RRRL
Â
The time complexity of the above approach is exponential.
Optimal Approach:Â
We can solve this problem by using dynamic programming in time and space complexity. Â
- If we store the best possible answers for all the bags from some beginning i to some ending j then there can be at mostÂ
such different subproblems.
- Let dp(i, j) represent the max score P1 can attain if the only remaining bags in the row start from i and end at j. Then the following hold:Â
- if it is P1’s turnÂ
- dp(i, j) = maximum of score of bag i + dp(i+1, j) or score of bag j + dp(i, j-1).
- if it is P2’s turnÂ
- dp(i, j) = minimum of dp(i+1, j) or dp(i, j-1).Â
Since the current bag’s score goes to P2 we don’t add it to dp(i, j).
- dp(i, j) = minimum of dp(i+1, j) or dp(i, j-1).Â
- if it is P1’s turnÂ
- To keep the track of the moves that take place at a given state we keep an additional boolean matrix which allows us to reconstruct the entire game moves that lead to the maximum score.
- The matrix leftBag(i, j) represents a state in which only the bag from i to j are present. leftBag(i, j) is 1 if it is optimal to pick the leftBag otherwise it is 0.
- The function getMoves uses this matrix to reconstruct the correct moves.
Below is the implementation of the above approach:Â
C++
// C++ implementation#include <bits/stdc++.h>#define maxSize 3000Â
using namespace std;Â
// dp(i, j) is the best// score possible if only// the bags from i, j were// present.Â
int dp[maxSize][maxSize];Â
// leftBag(i, j) is 1 if in the// optimal game the player picks// the leftmost bag when only the// bags from i to j are present.Â
bool leftBag[maxSize][maxSize];Â
// Function to calculate the maximum// valueint maxScore(vector<int> money){    // we will fill the dp table    // in a bottom-up manner. fill    // all states that represent    // lesser number of bags before    // filling states that represent    // higher number of bags.    // we start from states dp(i, i)    // as these are the base case of    // our DP solution.    int n = money.size();    int totalTurns = n;Â
    // turn = 1 if it is player 1's    // turn else 0. Who gets to pick    // the last bag(bottom-up so we    // start from last turn)    bool turn        = (totalTurns % 2 == 0) ? 0 : 1;Â
    // if bag is picked by P1 add it    // to the ans else 0 contribution    // to score.    for (int i = 0; i < n; i++) {        dp[i][i] = turn ? money[i] : 0;        leftBag[i][i] = 1;    }Â
    // 2nd last bag is picked by    // the other player.    turn = !turn;Â
    // sz represents the size    // or number of bags in    // the state dp(i, i+sz)    int sz = 1;Â
    while (sz < n) {Â
        for (int i = 0; i + sz < n; i++) {            int scoreOne = dp[i + 1][i + sz];            int scoreTwo = dp[i][i + sz - 1];Â
            // First player            if (turn) {                dp[i][i + sz]                    = max(money[i] + scoreOne,                          money[i + sz] + scoreTwo);Â
                // if leftBag has more profit                if (money[i] + scoreOne                    > money[i + sz] + scoreTwo)                    leftBag[i][i + sz] = 1;Â
                else                    leftBag[i][i + sz] = 0;            }Â
            // second player            else {                dp[i][i + sz]                    = min(scoreOne,                          scoreTwo);Â
                if (scoreOne < scoreTwo)                    leftBag[i][i + sz] = 1;Â
                else                    leftBag[i][i + sz] = 0;            }        }Â
        // Give turn to the        // other player.        turn = !turn;Â
        // Now fill states        // with more bags.        sz++;    }Â
    return dp[0][n - 1];}Â
// Using the leftBag matrix,// generate the actual game// moves that lead to the score.string getMoves(int n){Â Â Â Â string moves;Â Â Â Â int left = 0, right = n - 1;Â
    while (left <= right) {Â
        // if the bag is picked from left        if (leftBag[left][right]) {            moves.push_back('L');            left++;        }Â
        else {            moves.push_back('R');            right--;        }    }    return moves;}Â
// Driver Codeint main(){Â Â Â Â int ar[] = { 10, 80, 90, 30 };Â Â Â Â int arraySize = sizeof(ar) / sizeof(int);Â
    vector<int> bags(ar, ar + arraySize);    int ans = maxScore(bags);Â
    cout << ans << " " << getMoves(bags.size());    return 0;} |
Java
// Java Implementationpublic class Main{    static int maxSize = 3000;           // dp(i, j) is the best    // score possible if only    // the bags from i, j were    // present.    static int[][] dp = new int[maxSize][maxSize];        // leftBag(i, j) is 1 if in the    // optimal game the player picks    // the leftmost bag when only the    // bags from i to j are present.    static boolean[][] leftBag = new boolean[maxSize][maxSize];       // Function to calculate the maximum    // value    static int maxScore(int[] money)    {               // we will fill the dp table        // in a bottom-up manner. fill        // all states that represent        // lesser number of bags before        // filling states that represent        // higher number of bags.        // we start from states dp(i, i)        // as these are the base case of        // our DP solution.        int n = money.length;        int totalTurns = n;           // turn = 1 if it is player 1's        // turn else 0. Who gets to pick        // the last bag(bottom-up so we        // start from last turn)        boolean turn = (totalTurns % 2 == 0) ? false : true;           // if bag is picked by P1 add it        // to the ans else 0 contribution        // to score.        for (int i = 0; i < n; i++) {            dp[i][i] = turn ? money[i] : 0;            leftBag[i][i] = true;        }           // 2nd last bag is picked by        // the other player.        turn = !turn;           // sz represents the size        // or number of bags in        // the state dp(i, i+sz)        int sz = 1;           while (sz < n) {               for (int i = 0; i + sz < n; i++) {                int scoreOne = dp[i + 1][i + sz];                int scoreTwo = dp[i][i + sz - 1];                   // First player                if (turn) {                    dp[i][i + sz] = Math.max(money[i] + scoreOne, money[i + sz] + scoreTwo);                       // if leftBag has more profit                    if (money[i] + scoreOne > money[i + sz] + scoreTwo)                        leftBag[i][i + sz] = true;                       else                        leftBag[i][i + sz] = false;                }                   // second player                else {                    dp[i][i + sz] = Math.min(scoreOne, scoreTwo);                       if (scoreOne < scoreTwo)                        leftBag[i][i + sz] = true;                       else                        leftBag[i][i + sz] = false;                }            }               // Give turn to the            // other player.            turn = !turn;               // Now fill states            // with more bags.            sz++;        }           return dp[0][n - 1];    }       // Using the leftBag matrix,    // generate the actual game    // moves that lead to the score.    static String getMoves(int n)    {        String moves = "";        int left = 0, right = n - 1;           while (left <= right) {               // if the bag is picked from left            if (leftBag[left][right]) {                moves = moves + 'L';                left++;            }               else {                moves = moves + 'R';                right--;            }        }        return moves;    }         public static void main(String[] args) {        for(int i = 0; i < maxSize; i++)        {            for(int j = 0; j < maxSize; j++)            {                dp[i][j] = 0;                leftBag[i][j] = false;            }        }        int[] ar = { 10, 80, 90, 30 };        int arraySize = ar.length;               int[] bags = ar;        int ans = maxScore(bags);               System.out.print(ans + " " + getMoves(bags.length));    }}Â
// This code is contributed by divyes072019. |
Python3
# Python3 ImplementationmaxSize = 3000Â Â Â Â Â Â # dp(i, j) is the best# score possible if only# the bags from i, j were# present.dp = [[0 for i in range(maxSize)] for j in range(maxSize)]Â
# leftBag(i, j) is 1 if in the# optimal game the player picks# the leftmost bag when only the# bags from i to j are present.leftBag = [[False for i in range(maxSize)] for j in range(maxSize)]Â
# Function to calculate the maximum# valuedef maxScore(money):    # we will fill the dp table    # in a bottom-up manner. fill    # all states that represent    # lesser number of bags before    # filling states that represent    # higher number of bags.    # we start from states dp(i, i)    # as these are the base case of    # our DP solution.    n = len(money)    totalTurns = nÂ
    # turn = 1 if it is player 1's    # turn else 0. Who gets to pick    # the last bag(bottom-up so we    # start from last turn)    turn = 0 if (totalTurns % 2 == 0) else 1Â
    # if bag is picked by P1 add it    # to the ans else 0 contribution    # to score.    for i in range(n):        dp[i][i] = money[i] if turn else 0        leftBag[i][i] = 1Â
    # 2nd last bag is picked by    # the other player.    turn = not turnÂ
    # sz represents the size    # or number of bags in    # the state dp(i, i+sz)    sz = 1Â
    while sz < n:        i = 0        while i + sz < n:            scoreOne = dp[i + 1][i + sz]            scoreTwo = dp[i][i + sz - 1]Â
            # First player            if turn:                dp[i][i + sz] = max(money[i] + scoreOne, money[i + sz] + scoreTwo)Â
                # if leftBag has more profit                if (money[i] + scoreOne > money[i + sz] + scoreTwo):                    leftBag[i][i + sz] = 1                else:                    leftBag[i][i + sz] = 0Â
            # second player            else:                dp[i][i + sz] = min(scoreOne, scoreTwo)Â
                if (scoreOne < scoreTwo):                    leftBag[i][i + sz] = 1                else:                    leftBag[i][i + sz] = 0            i += 1Â
        # Give turn to the        # other player.        turn = not turnÂ
        # Now fill states        # with more bags.        sz += 1Â
    return dp[0][n - 1]Â
# Using the leftBag matrix,# generate the actual game# moves that lead to the score.def getMoves(n):Â Â Â Â moves = ""Â Â Â Â left, right = 0, n - 1Â
    while (left <= right):        # if the bag is picked from left        if (leftBag[left][right]):            moves = moves + 'L'            left += 1        else:           moves = moves + 'R'           right -= 1    return movesÂ
ar = [ 10, 80, 90, 30 ]arraySize = len(ar)Â
bags = arans = maxScore(bags)Â
print(ans, getMoves(len(bags)), sep=" ")Â
# This code is contributed by mukesh07. |
C#
// C# Implementationusing System;class GFG {         static int maxSize = 3000;          // dp(i, j) is the best    // score possible if only    // the bags from i, j were    // present.    static int[,] dp = new int[maxSize, maxSize];       // leftBag(i, j) is 1 if in the    // optimal game the player picks    // the leftmost bag when only the    // bags from i to j are present.    static bool[,] leftBag = new bool[maxSize, maxSize];      // Function to calculate the maximum    // value    static int maxScore(int[] money)    {        // we will fill the dp table        // in a bottom-up manner. fill        // all states that represent        // lesser number of bags before        // filling states that represent        // higher number of bags.        // we start from states dp(i, i)        // as these are the base case of        // our DP solution.        int n = money.Length;        int totalTurns = n;          // turn = 1 if it is player 1's        // turn else 0. Who gets to pick        // the last bag(bottom-up so we        // start from last turn)        bool turn = (totalTurns % 2 == 0) ? false : true;          // if bag is picked by P1 add it        // to the ans else 0 contribution        // to score.        for (int i = 0; i < n; i++) {            dp[i,i] = turn ? money[i] : 0;            leftBag[i,i] = true;        }          // 2nd last bag is picked by        // the other player.        turn = !turn;          // sz represents the size        // or number of bags in        // the state dp(i, i+sz)        int sz = 1;          while (sz < n) {              for (int i = 0; i + sz < n; i++) {                int scoreOne = dp[i + 1,i + sz];                int scoreTwo = dp[i,i + sz - 1];                  // First player                if (turn) {                    dp[i,i + sz] = Math.Max(money[i] + scoreOne, money[i + sz] + scoreTwo);                      // if leftBag has more profit                    if (money[i] + scoreOne > money[i + sz] + scoreTwo)                        leftBag[i,i + sz] = true;                      else                        leftBag[i,i + sz] = false;                }                  // second player                else {                    dp[i,i + sz] = Math.Min(scoreOne, scoreTwo);                      if (scoreOne < scoreTwo)                        leftBag[i, i + sz] = true;                      else                        leftBag[i, i + sz] = false;                }            }              // Give turn to the            // other player.            turn = !turn;              // Now fill states            // with more bags.            sz++;        }          return dp[0,n - 1];    }      // Using the leftBag matrix,    // generate the actual game    // moves that lead to the score.    static string getMoves(int n)    {        string moves = "";        int left = 0, right = n - 1;          while (left <= right) {              // if the bag is picked from left            if (leftBag[left,right]) {                moves = moves + 'L';                left++;            }              else {                moves = moves + 'R';                right--;            }        }        return moves;    }       static void Main()  {    for(int i = 0; i < maxSize; i++)    {        for(int j = 0; j < maxSize; j++)        {            dp[i,j] = 0;            leftBag[i,j] = false;        }    }    int[] ar = { 10, 80, 90, 30 };    int arraySize = ar.Length;      int[] bags = ar;    int ans = maxScore(bags);      Console.Write(ans + " " + getMoves(bags.Length));  }}Â
// This code is contributed by decode2207. |
Javascript
<script>    // Javascript Implementation         let maxSize = 3000;         // dp(i, j) is the best    // score possible if only    // the bags from i, j were    // present.         let dp = new Array(maxSize);    for(let i = 0; i < maxSize; i++)    {        dp[i] = new Array(maxSize);        for(let j = 0; j < maxSize; j++)        {            dp[i][j] = 0;        }    }      // leftBag(i, j) is 1 if in the    // optimal game the player picks    // the leftmost bag when only the    // bags from i to j are present.    let leftBag = new Array(maxSize);    for(let i = 0; i < maxSize; i++)    {        leftBag[i] = new Array(maxSize);        for(let j = 0; j < maxSize; j++)        {            leftBag[i][j] = false;        }    }Â
    // Function to calculate the maximum    // value    function maxScore(money)    {        // we will fill the dp table        // in a bottom-up manner. fill        // all states that represent        // lesser number of bags before        // filling states that represent        // higher number of bags.        // we start from states dp(i, i)        // as these are the base case of        // our DP solution.        let n = money.length;        let totalTurns = n;Â
        // turn = 1 if it is player 1's        // turn else 0. Who gets to pick        // the last bag(bottom-up so we        // start from last turn)        let turn = (totalTurns % 2 == 0) ? 0 : 1;Â
        // if bag is picked by P1 add it        // to the ans else 0 contribution        // to score.        for (let i = 0; i < n; i++) {            dp[i][i] = turn ? money[i] : 0;            leftBag[i][i] = 1;        }Â
        // 2nd last bag is picked by        // the other player.        turn = !turn;Â
        // sz represents the size        // or number of bags in        // the state dp(i, i+sz)        let sz = 1;Â
        while (sz < n) {Â
            for (let i = 0; i + sz < n; i++) {                let scoreOne = dp[i + 1][i + sz];                let scoreTwo = dp[i][i + sz - 1];Â
                // First player                if (turn) {                    dp[i][i + sz]                        = Math.max(money[i] + scoreOne,                              money[i + sz] + scoreTwo);Â
                    // if leftBag has more profit                    if (money[i] + scoreOne                        > money[i + sz] + scoreTwo)                        leftBag[i][i + sz] = 1;Â
                    else                        leftBag[i][i + sz] = 0;                }Â
                // second player                else {                    dp[i][i + sz]                        = Math.min(scoreOne,                              scoreTwo);Â
                    if (scoreOne < scoreTwo)                        leftBag[i][i + sz] = 1;Â
                    else                        leftBag[i][i + sz] = 0;                }            }Â
            // Give turn to the            // other player.            turn = !turn;Â
            // Now fill states            // with more bags.            sz++;        }Â
        return dp[0][n - 1];    }Â
    // Using the leftBag matrix,    // generate the actual game    // moves that lead to the score.    function getMoves(n)    {        let moves = "";        let left = 0, right = n - 1;Â
        while (left <= right) {Â
            // if the bag is picked from left            if (leftBag[left][right]) {                moves = moves + 'L';                left++;            }Â
            else {                   moves = moves + 'R';                right--;            }        }        return moves;    }         let ar = [ 10, 80, 90, 30 ];    let arraySize = ar.length;      let bags = ar;    let ans = maxScore(bags);      document.write(ans + " " + getMoves(bags.length));Â
// This code is contributed by divyeshrabadiya07.</script> |
110 RRRL
Â
Time and space complexities of this approach are .
Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!
