LeetCode刷題——除數博弈

題目

愛麗絲和鮑勃一起玩遊戲,他們輪流行動。愛麗絲先手開局。

最初,黑板上有一個數字 N 。在每個玩家的回合,玩家需要執行以下操作:

  • 選出任一 x,滿足 0 < x < N 且 N % x == 0 。
  • 用 N - x 替換黑板上的數字 N 。
    如果玩家無法執行這些操作,就會輸掉遊戲。

只有在愛麗絲在遊戲中取得勝利時才返回 True,否則返回 false。假設兩個玩家都以最佳狀態參與遊戲。

示例 1:

輸入:2
輸出:true
解釋:愛麗絲選擇 1,鮑勃無法進行操作。

示例 2:

輸入:3
輸出:false
解釋:愛麗絲選擇 1,鮑勃也選擇 1,然後愛麗絲無法進行操作。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/divisor-game

思路

這個題可以用歸納法和動態規劃法來接。先看下動態規劃法。

動態規劃

將所有的小於等於 N (包含N)的解都找出來,可以基於前面的解來推後面的。

dp[i]==False,說明愛麗絲會輸,反之說明會贏。要想愛麗絲贏,就要找到一個約數,使得愛麗絲取時爲True,並且刷新後的數爲False

class Solution(object):
    def divisorGame(self, N):
        """
        :type N: int
        :rtype: bool
        """
        dp = {} #True代表愛麗絲贏,False代表愛麗絲輸
        dp[2] = True 
        dp[1] = False
        import math
        for i in range(3,N+1):#需要包含N的情況
            dp[i] = False
            for j in range(1,int(math.sqrt(i))): #限定j的取值範圍
                if i % j == 0 and dp[i - j] == False: # 如果 選出任一j,滿足 i % j == 0,且下一個數字爲False
                    dp[i] = True #找得到這麼一個j,說明i是可以獲勝的
                    break 
        return dp[N]

歸納法

我們可以多舉幾個例子,然後找出規律:

  1. 假設 N = 1,愛麗絲無解(選出的值x必須0 < x < N),直接失敗;
  2. 假設 N = 2,愛麗絲可以選擇 x = 1,鮑勃 N = 2 - 1 = 1,無解,愛麗絲獲勝;
  3. 假設 N = 3,愛麗絲只可以選擇x=1,鮑勃N = 3 - 1 = 2,參考上面N=2,此時鮑勃獲勝
  4. 假設 N = 4,愛麗絲可以選擇 x = 1 使得鮑勃遇到 N = 3 的情況,參考上面,則愛麗絲獲勝;

大概可以得到一個規律:當N爲偶數時,愛麗絲能獲勝,否則失敗。

class Solution(object):
    def divisorGame(self,int N):
        return N % 2 == 0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章