有一排正数,玩家A和玩家B都可以看到。
每位玩家在拿走数字的时候,都只能从最左和最右的数中选择一个。玩家A先拿,玩家B再拿,两人交替拿走所有的数字。
两人都力争自己拿到的数的总和比对方多。请返回最后获胜者的分数。
例如∶5,2,3,4
玩家A先拿,当前他只能拿走5或者4。
如果玩家A拿走5,那么剩下2,3,4。轮到玩家B,此时玩家B可以选择2或4中的一个,如果玩家A拿走4,那么剩下5,2,3。轮到玩家B,此时玩家B可以选择5或3中的一个,…
利用动态规划求解
public static int win1(int[] arr){
if(arr == null || arr.length == 0){
retrun 0;
}
//返回的是先发或者后发者中的最大值,哪个大哪个就获胜
int sum = 0;
for(int i = 0; i < arr.length; i++){
sum += arr[i];
}
int fValue = f(arr, 0, arr.length - 1);
return Math.max(fValue, sum - fValue);
}
public static int win2(int[] arr){
if(arr == null || arr.length == 0){
retrun 0;
}
int[][] f = new int[arr.length][arr.length];
int[][] s = new int[arr.length][arr.length];
//动态规划可以以
for(int j = 0; j < arr.length; j++){
f[j][j] = arr[j];
for(int i = j - 1; i >= 0; i--){
f[i][j] = Math.max(arr[i] + s[i+1][j], arr[j] + s[i][j-1]);
s[i][j] = Math.min(f[i+1][j], f[i][j-1]);
}
}
}
//先发过程
public static int f(int[] arr, int i, int j){
//如果只有一个数,因为先发,这个数肯定被我拿了
if(i == j){
return arr[i];
}
//要么先那arr[i],然后在i + 1-j的范围内后发情况下能获得的收益
return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1));
}
//后发过程
public static int s(int[] arr, int i, int j){
//如果只有一个数的话,因为后发,这个数我肯定拿不到,所以返回值为0
if(i == j){
return 0;
}
//剩下两种决策中差的给你,因为最好的选择由不得我
//如果先发拿走了arr[i],那我就是在i+1,j中先发
//如果先发拿走了arr[j],那我就是在i,j-1中先发
return Math.min(f(arr, i + 1, j), f(arr, i, j - 1));
}