有 n 个不同价值的硬币排成一条线。两个参赛者轮流从 左边 依次拿走 1 或 2 个硬币,直到没有硬币为止。计算两个人分别拿到的硬币总价值,价值高的人获胜。
请判定 先手玩家 必胜还是必败?
若必胜, 返回 true, 否则返回 false.
博弈型动态规划
dp数组每个点代表先手选择n个硬币 是否可以获胜
赢得关键是让对手选到更少价值的硬币 自己拿到价值总和的一半以上 就可以获得胜利
每次选择都有四种情况 分别dfs
用二维数组记录搜索过的情况 避免重复
public class Solution {
/**
* @param values: a vector of integers
* @return: a boolean which equals to true if the first player will win
*/
int[] dp;
boolean[] flag;
public boolean firstWillWin(int[] values) {
dp = new int[values.length + 1];
flag = new boolean[values.length + 1];
int sum = 0;
for(int num : values)
sum += num;
return 2 * memorySearch(values.length, values) > sum;
}
private int memorySearch(int n, int[] values){
if(flag[n] == true)
return dp[n];
flag[n] = true;
if(n <= 0){
dp[n] = 0;
}
else if(n == 1){
dp[n] = values[values.length - 1];
}
else if(n == 2){
dp[n] = values[values.length - 1] + values[values.length - 2];
}
else if(n == 3){
dp[n] = values[values.length - 2] + values[values.length - 3];
}
else{
dp[n] = Math.max((Math.min(memorySearch(n-2, values), memorySearch(n-3, values)) + values[values.length - n]),
(Math.min(memorySearch(n-3, values), memorySearch(n-4, values)) + values[values.length - n] + values[values.length - n + 1]));
}
return dp[n];
}
}