In the "100 game" two players take turns adding, to a running total, any integer from 1 to 10. The player who first causes the running total to reach or exceed 100 wins.
What if we change the game so that players cannot re-use integers?
For example, two players might take turns drawing from a common pool of numbers from 1 to 15 without replacement until they reach a total >= 100.
Given two integers maxChoosableInteger and desiredTotal, return true if the first player to move can force a win, otherwise return false. Assume both players play optimally.
Example 1:
Input: maxChoosableInteger = 10, desiredTotal = 11
Output: false
Explanation:
No matter which integer the first player choose, the first player will lose.
The first player can choose an integer from 1 up to 10.
If the first player choose 1, the second player can only choose integers from 2 up to 10.
The second player will win by choosing 10 and get a total = 11, which is >= desiredTotal.
Same with other integers chosen by the first player, the second player will always win.
Example 2:
Input: maxChoosableInteger = 10, desiredTotal = 0
Output: true
Example 3:
Input: maxChoosableInteger = 10, desiredTotal = 1
Output: true
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/can-i-win
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
带储存的dfs算法,用一个map<Integer, Boolean>放置当前如果到达了某个状态,即已经被选了某些数字的场景,这个状态能不能赢。Integer用位来表示,哪些被选中了的,如integer为5,那它的二进制表示是101,那就表示了,当第1个与第3个数字(即1和3)被选中后的这个状态,是不是就赢了。
class Solution {
public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
if (maxChoosableInteger >= desiredTotal)
return true;
if (maxChoosableInteger * (maxChoosableInteger + 1) / 2 < desiredTotal)
return false;
// 用dp来放置某个状态的结果。
// key是integer,表示的是当前某个状态,
// 如integer为5,那它的二进制表示是101,那就表示了,当第1个与第3个数字(即1和3)被选中后的这个状态,是不是就赢了。
Map <Integer, Boolean> dp = new HashMap<>();
return canWin(desiredTotal, maxChoosableInteger, dp, 0);
}
private boolean canWin(int desiredTotal, int maxChoosableInteger, Map<Integer, Boolean> dp, int state) {
if (dp.containsKey(state)) {
return dp.get(state);
}
for (int i = 1; i <= maxChoosableInteger; i++) {
// 把当前要数字对应的位,与当前状态进行与操作,如果结果是0,说明没有被用过,如果结果是1,说明被用到过了。
boolean unVisited = (( 1 << i ) & state) == 0;
if (unVisited) {
// 如果选择了i,已经满足了要求,那么当到达这个状态时,做选择的人能赢
// 如果不能满足要求,那么就看desiredTotal - i如果不能满足,那么desiredTotal肯定满足,因为i还没有被选嘛。
if (desiredTotal <= i || !canWin(desiredTotal - i, maxChoosableInteger, dp, (( 1 << i ) | state)) ) {
dp.put(state, true);
return true;
}
}
}
dp.put(state, false);
return false;
}
}