[Coding Made Simple] Optimal Strategy Game Pick from Ends of array

N pots, each with some number of gold coins, are arranged in a line. You are playing a game against another player. You take turns picking a pot of gold. You may pick a pot from either end of the line, remove the pot, and keep the gold pieces. The player with the most gold at the end wins. Develop a strategy for playing this game.

After drawing the following flow diagram, it is clear that we have overlapping subproblems such as p1 for A[1-6]. As a result, we‘ll use dynamic programming here.

Solution 1. Dynamic Programming, only from player 1‘s perspective.

State: T[i][j]: the max value player 1 can get when pots[i......j] are available.

Function: T[i][j] = Max {pots[i] + Min {T[i + 2][j]},  T[i + 1][j - 1],    pots[j] + Min {T[i + 1][j - 1], T[i][j - 2]} }.   Min is used here is because player 2 is trying to play for the best strategy too.

Init: If there is only 1 pot, pick it; If there are 2 pots, pick the one that has a bigger value.

Answer: T[0][pots.length - 1]

 1 import java.util.ArrayList;
 2
 3 public class OptimalGamePick {
 4     private ArrayList<Integer> picks;
 5     public int getOptimalStrategy(int[] pots) {
 6         picks = new ArrayList<Integer>();
 7         if(pots == null || pots.length == 0){
 8             return 0;
 9         }
10         int[][] T = new int[pots.length][pots.length];
11         for(int i = 0; i < pots.length; i++) {
12             T[i][i] = pots[i];
13         }
14         for(int i = 0; i < pots.length - 1; i++) {
15             T[i][i + 1] = Math.max(pots[i], pots[i + 1]);
16         }
17         for(int len = 3; len <= pots.length; len++) {
18             for(int i = 0; i <= pots.length - len; i++) {
19                 T[i][i + len - 1] = Math.max(pots[i] + Math.min(T[i + 2][i + len - 1], T[i + 1][i + len - 2]),
20                                              pots[i + len - 1] + Math.min(T[i + 1][i + len -2], T[i][i + len - 3]));
21             }
22         }
23         //reconstruct player 1‘s picks
24         int start = 0, end = pots.length - 1;
25         while(end - start >= 2) {
26             int pickFront = pots[start] + Math.min(T[start + 2][end], T[start + 1][end - 1]);
27             int pickEnd = pots[end] + Math.min(T[start + 1][end - 1], T[start][end - 2]);
28             if(pickFront > pickEnd) {
29                 picks.add(start);
30                 if(T[start + 2][end] < T[start + 1][end - 1]) {
31                     start++;
32                 }
33                 else {
34                     end--;
35                 }
36                 start++;
37             }
38             else {
39                 picks.add(end);
40                 if(T[start + 1][end - 1] < T[start][end - 2]) {
41                     start++;
42                 }
43                 else {
44                     end--;
45                 }
46                 end--;
47             }
48         }
49         if(end - start == 1) {
50             if(pots[start] > pots[end]) {
51                 picks.add(start);
52             }
53             else {
54                 picks.add(end);
55             }
56         }
57         else {
58             picks.add(start);
59         }
60         return T[0][pots.length - 1];
61     }
62     public static void main(String[] args) {
63         int[] pots = {3, 9, 1, 2};
64         OptimalGamePick test = new OptimalGamePick();
65         System.out.println(test.getOptimalStrategy(pots));
66     }
67 }

Solution 2.  Dynamic Programming, from both player 1 and 2‘s perspective.

State: T[i][j] stores the max value both players can get given pots i to j. Whoever picks first becomes player 1, so as the range of pots changes, player 1 and player 2 take turns to pick first.

Function:  If player 1 picks pots[i], then for pots i + 1 to j he becomes player 2 as he is the second player to pick from i + 1 to j.

   T[i][j]. first = max {T[i + 1][j].second + pots[i],  T[i][j - 1].second + pots[j]};

   T[i][j].second = T[i + 1][j].first or T[i][j - 1].first, depending on which pot was picked previously by the other player.

 1 public ResultEntry getOptimalStrategy(int[] pots) {
 2     ResultEntry[][] T = new ResultEntry[pots.length][pots.length];
 3     for(int i = 0; i < T.length; i++) {
 4         for(int j = 0; j < T[0].length; j++) {
 5             T[i][j] = new ResultEntry(0, 0);
 6         }
 7     }
 8     for(int i = 0; i < T.length; i++) {
 9         T[i][i].p1 = pots[i];
10     }
11     for(int i = 0; i < T.length - 1; i++) {
12         T[i][i + 1].p1 = Math.max(pots[i], pots[i + 1]);
13         T[i][i + 1].p2 = Math.min(pots[i], pots[i + 1]);
14     }
15     for(int len = 3; len <= pots.length; len++) {
16         for(int i = 0; i <= pots.length - len; i++) {
17             int pickFront = pots[i] + T[i + 1][i + len - 1].p2;
18             int pickEnd = pots[i + len - 1] + T[i][i + len -2].p2;
19             if(pickFront >= pickEnd) {
20                 T[i][i + len - 1].p1 = pickFront;
21                 T[i][i + len - 1].p2 = T[i + 1][i + len - 1].p1;
22             }
23             else {
24                 T[i][i + len - 1].p1 = pickEnd;
25                 T[i][i + len - 1].p2 = T[i][i + len - 2].p1;
26             }
27         }
28     }
29     return T[0][pots.length - 1];
30 }
时间: 2025-01-17 00:02:39

[Coding Made Simple] Optimal Strategy Game Pick from Ends of array的相关文章

[Coding Made Simple] Optimal Binary Search Tree

Given keys and frequency at which these keys are searched, how would you create a binary search tree from these keys such that the cost of searching is minimum. The cost of searching is defined as the sum of all node's search frequency * its depth; R

[Coding Made Simple] Maximum Subsquare surrounded by &#39;X&#39;

Given a 2D matrix where every element is either 'O' or 'X', find the largest subsquare surrounded by 'X'. Examples: Input: mat[N][N] = { {'X', 'O', 'X', 'X', 'X'}, {'X', 'X', 'X', 'X', 'X'}, {'X', 'X', 'O', 'X', 'O'}, {'X', 'X', 'X', 'X', 'X'}, {'X',

[Coding Made Simple] Box Stacking

Given boxes of different dimensions, stack them on top of each other to get maximum height such that box on top has strictly less length and width than box under it. Algorithm. 1. get all the box permutation with each permutation's length >= width; s

[Coding Made Simple] Matrix Chain Multiplication

Given some matrices, in what order you would multiply them to minimize cost of multiplication. The following problem formulation is extracted from this link. Problem Formulation Note that although we can use any legal parenthesization, which will lea

[Coding Made Simple] Coin Changes Minimum Number of Coins

Given coins of certain denominations and a total, how many minimum coins would you need to make this total? Dynamic Programming solution State: T[i][j]: given the first i coins, the min number of coins needed to make a total of j. Function: case 1. T

[Coding Made Simple] Sum Query in 2D Immutable Array

Given a 2D immutable array,  Write an efficient program to support any given sub-rectangle sum query in this 2D matrix. A simple solution is to add each entry inside the sub-rectangle. The runtime is O(n * m). The problem of this solution is that for

[Coding Made Simple] Burst Balloon

Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and r

[Coding Made Simple] Minimum Cost Path

Given a 2 dimensional matrix, find minimum cost path to reach bottom right from top left provided you can only from down and right. For a 5 * 5 matrix, think of solving this problem by breaking it into smaller subproblems. And overlapping subproblems

[Coding Made Simple] Number without consecutive 1s in binary representation

Given a number n, find the total number of numbers from 0 to 2^n - 1 which do not have consecutive 1s in their binary representation. Solution.  This problem is the equivalence of fibonacci sequence. For a given n, f(n) = f(n - 1) + f(n - 2). 1 publi