[464]Can I Win
# 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
#
#
#
# Constraints:
#
#
# 1 <= maxChoosableInteger <= 20
# 0 <= desiredTotal <= 300
#
# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
def __init__(self):
self.mem = {}
def dfs(self, mci, dt, state, sum_):
# 这个是必须的,不然后手self.dfs(mci, dt, state | 1 << i - 1, sum_ + i)返回False, 导致先手的结果为True
if mci * (mci + 1) / 2 < dt:
self.mem[state] = False
return False
if state in self.mem:
return self.mem[state]
# 注意range的起始和结束的区间
for i in range(1, mci + 1):
# 状态从0号bit为开始, 所以为i-1
if 1 << i - 1 & state:
continue
#先手的求和大于i或者后手的结果为False
if sum_ + i >= dt or not self.dfs(mci, dt, state | 1 << i - 1, sum_ + i):
self.mem[state] = True
return True
self.mem[state] = False
return False
def canIWin(self, maxChoosableInteger: int, desiredTotal: int) -> bool:
self.dfs(maxChoosableInteger, desiredTotal, 0, 0)
return self.mem[0]
# leetcode submit region end(Prohibit modification and deletion)
if __name__ == '__main__':
so = Solution()
maxChoosableInteger = 5
desiredTotal = 50
res = so.canIWin(maxChoosableInteger, desiredTotal)
print(res)