C++ 中我能贏嗎


假設在一個名為“100 遊戲”的遊戲中,兩位玩家輪流將任意 1 到 10 之間的整數加到一個執行總和中。第一個使執行總和達到或超過 100 的玩家獲勝。那麼,如果我們更改遊戲規則,使得玩家不能重複使用整數,會發生什麼情況呢?

例如,如果兩位玩家輪流從 1 到 15 的公共數字池中抽取數字(不放回),直到他們達到總和 >= 100。

因此,假設給定一個整數 maxChoosableInteger 和另一個整數 desired total,確定第一個移動的玩家是否可以迫使獲勝,假設兩個玩家都以最佳方式進行遊戲。

我們始終可以假設 maxChoosableInteger 的值不會大於 20,並且 desired total 的值不會大於 300。因此,如果輸入為 maxChooseableInteger = 20,並且 desired total 為 11,則結果將為 false。無論第一個玩家選擇什麼,第一個玩家都會輸。

為了解決這個問題,我們將遵循以下步驟 -

  • 建立一個名為 dp 的大小為 2^21 的陣列

  • 定義一個名為 solve() 的方法,它將接收 n、s 和 mask 作為引數。

  • 如果 s <= 0,則返回 false

  • 如果 dp[mask] 不為 -1,則返回 dp[mask]

  • 設定 ret := false

  • 對於 I 的範圍從 1 到 n

    • 如果(將 mask 向右移動 I 位)為奇數,則

      • ret := ret OR (solve(n, s – i, mask XOR 2^i) 的反值)

  • dp[mask] := ret

  • 返回 ret

  • 從主方法中執行以下操作

  • 如果 desiredTotal <= 0,則返回 true

  • 對於 I 的範圍從 0 到 2^21

    • dp[i] := -1

  • 如果 desiredTotal > (前 n 個數字的總和),則返回 false

  • 返回 solve(n, desiredTotal, 0)

示例(C++)

讓我們看看下面的實現,以便更好地理解 -

 線上演示

#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
   int dp[1 << 21];
   bool solve(int n, int s, int mask){
      if(s <= 0) return false;
      if(dp[mask] != -1) return dp[mask];
      bool ret = false;
      for(int i = 1; i <= n; i++){
         if(!((mask >> i) & 1)){
            ret |= (!solve(n, s - i, (mask ^ (1 << i))));
         }
      }
      return dp[mask] = ret;
   }
   bool canIWin(int n, int desiredTotal) {
      if(desiredTotal <= 0) return true;
      for(int i = 0; i < (1 << 21); i++)dp[i] = -1;
      if(desiredTotal > (n * (n + 1)/ 2))return false;
      return solve(n, desiredTotal, 0);
   }
};
main() {
Solution ob;
cout << (ob.canIWin(10,11));
}

輸入

10
11

輸出

0

更新於: 2020-04-29

213 次瀏覽

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告