1. 程式人生 > >464.我能贏嗎

464.我能贏嗎

在 "100 game" 這個遊戲中,兩名玩家輪流選擇從 1 到 10 的任意整數,累計整數和,先使得累計整數和達到 100 的玩家,即為勝者。

如果我們將遊戲規則改為 “玩家不能重複使用整數” 呢?

例如,兩個玩家可以輪流從公共整數池中抽取從 1 到 15 的整數(不放回),直到累計整數和 >= 100。

給定一個整數 maxChoosableInteger (整數池中可選擇的最大數)和另一個整數 desiredTotal(累計和),判斷先出手的玩家是否能穩贏(假設兩位玩家遊戲時都表現最佳)?

你可以假設 maxChoosableInteger

 不會大於 20, desiredTotal 不會大於 300。

示例:

輸入:
maxChoosableInteger = 10
desiredTotal = 11

輸出:
false

解釋:
無論第一個玩家選擇哪個整數,他都會失敗。
第一個玩家可以選擇從 1 到 10 的整數。
如果第一個玩家選擇 1,那麼第二個玩家只能選擇從 2 到 10 的整數。
第二個玩家可以通過選擇整數 10(那麼累積和為 11 >= desiredTotal),從而取得勝利.
同樣地,第一個玩家選擇任意其他整數,第二個玩家都會贏。

class Solution {
public:
    bool canIWin(int maxChoosableInteger, int desiredTotal) {
        if (maxChoosableInteger >= desiredTotal) return true;
        if (maxChoosableInteger * (maxChoosableInteger + 1) / 2 < desiredTotal) return false;
        unordered_map<int, bool> m;
        return canWin(maxChoosableInteger, desiredTotal, 0, m);
    }
    bool canWin(int length, int total, int used, unordered_map<int, bool>& m) {
        if (m.count(used)) return m[used];
        for (int i = 0; i < length; ++i) {
            int cur = (1 << i);
            if ((cur & used) == 0) {
                if (total <= i + 1 || !canWin(length, total - (i + 1), cur | used, m)) {
                    m[used] = true;
                    return true;
                }
            }
        }
        m[used] = false;
        return false;
    }
};