动态规划:博弈型
博弈型dp一般从第一步分析,而不是最后一步,需要开n+1
1、LintCode 394 Coins in a Line
【问题】有 n 个硬币排成一条线。两个参赛者轮流从右边依次拿走 1 或 2 个硬币,直到没有硬币为止。拿到最后一枚硬币的人获胜。请判定 先手玩家必胜还是必败?
【分析】从第一步开始,一开始有n个硬币,A可以拿一个或两个硬币,这样B则对应拿n-1个或n-2个硬币,A肯定会采取策略让自己获胜。然后不断拿。假设一开始有5个硬币,可以画出如果所示的树形结构,必败就是自己无路可逃,必胜就是有赢的可能。
【状态】设dp[i]表示面对i个硬币,是否先手必胜则有下面几种情况
dp[i] = true,f[i-1]==false || f[i-2]==false
(对手拿1个或2个都是必败的情况)dp[i] = false,f[i-1]==true && f[i-2]==true
(对手拿1个或2个都是必胜的情况)
【初始情况与边界】
dp[0] = 0
,面对0个硬币,必败dp[1] = dp[2] = true
public boolean firstWillWin(int n) {
if (n == 0) {
return false;
}
if (n <= 2) {
return true;
}
boolean[] dp = new boolean[n + 1];
dp[0] = false;
dp[1] = true;
for (int i = 2; i <= n; i++) {
// if (dp[i - 1] == true && dp[i - 2] == true) {
// dp[i] = false;
// } else {
// dp[i] = true;
// }
dp[i] = !dp[i - 1] || !dp[i - 2];
}
return dp[n];
}