私は次のように減らした問題を与えられました:あなたはすべてのものを持つ2進数(例えば11111)と同じ長さの2進数のセット(00101、10000、01100、00100、11100)を与えられます。2人のプレーヤーAとBがいます。各ターンで、プレーヤーはメインの2進数(11111)から、2の2進数のANDが小さい数字になるように、小さい数字のいずれかを引くことができます。次に、次のプレーヤーは結果から減算することができます。もう引き算できないプレイヤーは負けます。例えば。
A B
11111 11010 // Now A cannot subtract
-00101 -10000 // anymore in the next turn.
------- ------ // So B wins the game.
11010 01010
------- ------
両方のプレーヤーが最適にプレーする場合(彼らの勝利のために最良の選択をする)、私はどちらのプレーヤーが与えられた2進数の組み合わせで勝つかを見つけなければなりません。
O(n ^ 2)アプローチを試しましたが、もっと速い方法はありますか?
編集:O(n ^ 2):ここで、nは状態の数です。長さ6(111111)の2進数の場合、2^6の状態が可能です。だから私の複雑さはO((2 ^ 6)^ 2)です。
編集:すべての可能な状態を生成するマイコード:
void makeAllStates() /* Bottom Up Approach. Starting from 00000 and going to 11111 */
{
// bool states[i] : True if state[i] is a winning position.
// bool isWord[i] : True if the given state matches a smaller number. (eg. If the main number has been reduced to 10110 and there is a smaller number 10110, then isWord[i] is true.
// bool visited[i] : True If the given state has been visited
// int statecount : Total number of states
int temp;
for(int xx=1;xx<stateCount;xx++)
{
for(int yy=1;yy<stateCount;yy++)
{
if(xx&yy)
continue;
if(!(isWord[xx] || isWord[yy]))
continue;
if(!visited[yy])
continue;
temp = xx^yy;
if(isWord[temp])
continue;
if(states[temp])
continue;
if(isWord[xx] && isWord[yy])
states[temp] = false;
else
{
if(isWord[xx])
states[temp] = !states[yy];
else
states[temp] = !states[xx];
}
visited[temp] = true;
if(temp == stateCount-1 && states[temp])
{
return;
}
}
}
}