464. 我能赢吗(精髓)

  • 千万注意这题是累计整数和

    1. class Solution {
    2. public:
    3. unordered_map<int, bool> memo;//记忆化剪枝
    4. bool canIWin(int maxChoosableInteger, int desiredTotal) {
    5. if ((1 + maxChoosableInteger) * (maxChoosableInteger) / 2 < desiredTotal) {
    6. return false;
    7. }//特殊情况。
    8. return dfs(maxChoosableInteger, 0, desiredTotal, 0);
    9. }
    10. bool dfs(int maxChoosableInteger, int usedNumbers, int desiredTotal, int currentTotal) {//用一个整数来表示已经选择的数字集合,看二进制位i是否取1来判断是否选择了i。
    11. // 每一层的玩家不同, 但是目的都是当前层能获胜 || 下一层不能获胜则当前层能获胜
    12. if (!memo.count(usedNumbers)) {//如果记忆中没有
    13. bool res = false;
    14. for (int i = 0; i < maxChoosableInteger; i++) {
    15. if (((usedNumbers >> i) & 1) == 0) {//当前位置没有选择
    16. if (i + 1 + currentTotal >= desiredTotal) {//选当前位后可以达成目标。
    17. res = true;
    18. break;
    19. }
    20. if (!dfs(maxChoosableInteger, usedNumbers | (1 << i), desiredTotal, currentTotal + i + 1)) {//这里表示对方输了。因为对方最终无法达到目标
    21. res = true;
    22. break;
    23. }
    24. }
    25. }
    26. memo[usedNumbers] = res;//使用记忆化,不用浪费时间。
    27. }
    28. return memo[usedNumbers];
    29. }
    30. };

    猫和老鼠系列