-
Notifications
You must be signed in to change notification settings - Fork 0
464. Can I Win
In the "100 game," two players take turns adding, to a running total, any integer from 1..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 of 1..15 without replacement until they reach a total >= 100.
Given an integer maxChoosableInteger and another integer desiredTotal, determine if the first player to move can force a win, assuming both players play optimally.
You can always assume that maxChoosableInteger will not be larger than 20 and desiredTotal will not be larger than 300.
Example
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.
判断can win的条件为
1. 如果选择一个数,大于或等于total,则win;
2. 如果最大的可选数字小于total,但是与其他任意一个数字的和大于或等于total,则肯定loose;
3. 如果所有数的和小于total,则两者都不能win。
这里若考虑取一个数后的所有情况,则时间复杂度为O(n!)。 因此,可以采用dynamic programming的思想,将中间结果存储起来。
因为maxChoosableInteger不超过20,因此可以采用一个int来表示所有的可选数字,'1'表示已选过,'0'表示未选。
用Boolean[] win[1 << maxChoosableInteger]来存储中间结果。
public class Solution {
private Boolean[] win;
private int chosen;
public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
if(desiredTotal == 0) return true;
if(maxChoosableInteger*(maxChoosableInteger+1)/2 < desiredTotal) return false;
win = new Boolean[1 << maxChoosableInteger];
chosen = 0;
return canWin(maxChoosableInteger, desiredTotal, 0);
}
private boolean canWin(int n, int total, int now) {
if(win[chosen] != null) return win[chosen];
if(now >= total) {
win[chosen] = false;
return false;
}
for(int i = 1; i <= n; i++) {
int pick = 1 << (i-1);
if((pick & chosen) == 0) {
chosen ^= pick;
boolean uWin = !canWin(n, total, now + i);
chosen ^= pick;
if(uWin) {
win[chosen] = true;
return true;
}
}
}
win[chosen] = false;
return false;
}
}