C ++で勝つことはできますか?
「100ゲーム」と呼ばれるゲームで、2人のプレーヤーが交代で、1から10までの整数を現在の合計に追加するとします。 100を超えると、彼/彼女が勝ちます。では、プレーヤーが整数を再利用できないようにゲームを変更したらどうなるでしょうか?
たとえば、2人のプレーヤーが交代で、合計> =100に達するまで、交換せずに1..15の共通のプールから抽選を行う場合。
したがって、整数maxChoosableIntegerと別の整数の希望する合計が与えられたとすると、両方のプレーヤーが最適にプレーすると仮定して、最初に移動したプレーヤーが勝利を強制できるかどうかを判断します。
maxChoosableIntegerは値20を超えず、目的の合計は300を超えないと常に想定できます。したがって、入力がmaxChooseableInteger =20で、目的の合計が11の場合、結果はfalseになります。最初のプレーヤーが選択しても、最初のプレーヤーは負けます。
これを解決するには、次の手順に従います-
-
サイズ2^21
のdpという配列を作成します -
メソッドsolve()を定義します。これには、n、s、およびマスクが必要です。
-
s <=0の場合、falseを返します
-
dp [mask]が-1でない場合は、dp [mask]
を返します。 -
set ret:=false
-
1からnの範囲のIの場合
-
(マスクを1ビット右にシフトする)が奇数の場合、
-
ret:=ret OR(solve(n、s – i、mask XOR 2 ^ i)の逆)
-
-
-
dp [マスク]:=ret
-
retを返す
-
メインの方法から、次のようにします
-
必要に応じてTotal<=0の場合、trueを返します
-
0から2^21の範囲のIの場合
-
dp [i]:=-1
-
-
必要に応じてTotal>(最初の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
-
名前空間はC++でネストできますか?
はい、名前空間はC++でネストできます。次のように、別の名前空間内に1つの名前空間を定義できます- 構文 namespace namespace_name1 { // code declarations namespace namespace_name2 { // code declarations } } 次のような解決演算子を使用して、ネストされた名前空間のメンバーにアクセスできます- // to access members of namespace_name2 us
-
C ++で「オブジェクトを返す」方法は?
オブジェクトはクラスのインスタンスです。メモリは、オブジェクトが作成されたときにのみ割り当てられ、クラスが定義されたときは割り当てられません。 returnキーワードを使用して、関数からオブジェクトを返すことができます。これを実証するプログラムは次のとおりです- 例 #include <iostream> using namespace std; class Point { private: int x; int y; public: Point(in