[Coding Made Simple] Optimal Strategy Game Pick from Ends of array
Posted Push your limit!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 }
以上是关于[Coding Made Simple] Optimal Strategy Game Pick from Ends of array的主要内容,如果未能解决你的问题,请参考以下文章
[Coding Made Simple] Longest Increasing Subsequence
[Coding Made Simple] String Interleaving
[Coding Made Simple] Matrix Chain Multiplication
[Coding Made Simple] Burst Balloon