464. 我能赢吗(精髓)
千万注意这题是累计整数和
class Solution {
public:
unordered_map<int, bool> memo;//记忆化剪枝
bool canIWin(int maxChoosableInteger, int desiredTotal) {
if ((1 + maxChoosableInteger) * (maxChoosableInteger) / 2 < desiredTotal) {
return false;
}//特殊情况。
return dfs(maxChoosableInteger, 0, desiredTotal, 0);
}
bool dfs(int maxChoosableInteger, int usedNumbers, int desiredTotal, int currentTotal) {//用一个整数来表示已经选择的数字集合,看二进制位i是否取1来判断是否选择了i。
// 每一层的玩家不同, 但是目的都是当前层能获胜 || 下一层不能获胜则当前层能获胜
if (!memo.count(usedNumbers)) {//如果记忆中没有
bool res = false;
for (int i = 0; i < maxChoosableInteger; i++) {
if (((usedNumbers >> i) & 1) == 0) {//当前位置没有选择
if (i + 1 + currentTotal >= desiredTotal) {//选当前位后可以达成目标。
res = true;
break;
}
if (!dfs(maxChoosableInteger, usedNumbers | (1 << i), desiredTotal, currentTotal + i + 1)) {//这里表示对方输了。因为对方最终无法达到目标
res = true;
break;
}
}
}
memo[usedNumbers] = res;//使用记忆化,不用浪费时间。
}
return memo[usedNumbers];
}
};
猫和老鼠系列