Grundyのゲームでヒープを2つのヒープに分割するにはどうすればいいですか?Grundyのゲームは2つ以上のヒープに拡張されました
ヒープを任意の数のヒープに分割するとどうなりますか(2つは同じではありません)?
Grundyのゲームでヒープを2つのヒープに分割するにはどうすればいいですか?Grundyのゲームは2つ以上のヒープに拡張されました
ヒープを任意の数のヒープに分割するとどうなりますか(2つは同じではありません)?
このタイプのゲームは、本シリーズ "Winning Ways for your Mathematical Plays"で非常に詳細に分析されています。あなたが探しているものの大半は、おそらくボリューム1にあります。
また、Nimbers (Wikipedia),Sprague-Grundy theorem (Wikipedia)のリンクを参照するか、「combinatorial game theory」を検索してください。
これに関する私の知識はかなり錆びているので、私はこの特定の問題に関して自分自身を助けることはできません。あなたがすでに私がリンクしているすべてを知っていたら、私の言い訳。
編集:一般に、これらのタイプのゲームを解決する方法は、スタックサイズを「構築」することです。だから、1のスタックから始め、誰が最適なプレーで勝利するかを決めます。次に、2のスタックについて同じことを実行します。これは1 &に分割することができます。1に移動すると、1に変更することができます。& 2. 4と同じです(ここではよりトリッキーになります):3 & 1または2 & 2、Spague-Grundy定理&を使用して、nimbersの代数ルールを使用して、誰が勝つかを計算することができます。あなたが答えを知る必要があるスタックサイズに達するまで続けてください。
編集2:コメントの中で私が話していたウェブサイトはダウンしているようです。ここにそのバックアップのリンクがあります:Wayback Machine - Introduction to Combinatorial Games。
グランディーのゲーム、およびそれのような多くのゲームでは、このようなアルゴリズムを用いて解決することができます。
//returns a Move object representing the current player's optimal move, or null if the player has no chance of winning
function bestMove(GameState g){
for each (move in g.possibleMoves()){
nextState = g.applyMove(move)
if (bestMove(nextState) == null){
//the next player's best move is null, so if we take this move,
//he has no chance of winning. This is good for us!
return move;
}
}
//none of our possible moves led to a winning strategy.
//We have no chance of winning. This is bad for us :-(
return null;
}
GameStateの実装と移動がゲームに依存します。 Grundyのゲームでは、どちらもシンプルです。
GameState
は、ゲーム内の各ヒープのサイズを表す整数のリストを格納します。
Move
は、整数のinitialHeapSize
と、resultingHeapSizes
の整数のリストを格納します。
GameState::possibleMoves
は、そのヒープサイズリストを反復し、それぞれの法的分割を決定します。
GameState::applyMove(Move)
は、与えられた動きがボードに適用されることを除き、GameStateのコピーを返します。
GameState::possibleMoves
は「クラシック」グランディーのゲームのようになどに実装することができます。
function possibleMoves(GameState g){
moves = []
for each (heapSize in g.heapSizes){
for each (resultingHeaps in possibleDivisions(heapSize)){
Move m = new Move(heapSize, resultingHeaps)
moves.append(m)
}
}
return moves
}
function possibleDivisions(int heapSize){
divisions = []
for(int leftPileSize = 1; leftPileSize < heapSize; leftPileSize++){
int rightPileSize = heapSize - leftPileSize
if (leftPileSize != rightPileSize){
divisions.append([leftPileSize, rightPileSize])
}
}
return divisions
}
が、これはルール「不平等な山の任意の数に分割」を使用して変更の実装を変更するだけですpossibleDivisions
私はまさにそれを計算していないが、最適化されていないbestMoveはかなりクレイジー最悪の場合の実行時間を有します。約12石の開始状態を開始すると、あなたは長い待ち時間を取るでしょう。したがって、パフォーマンスを向上させるにはmemoizationを実装する必要があります。最良の結果を得るために
、ソートされた各GameStateのヒープサイズのリストを維持し、サイズ2または1
申し訳ありませんが、これは独自のアルゴリズムですか、それともどこかに見つかりましたか? – Sushant
bestMoveは、[Minimax](http://en.wikipedia.org/wiki/Minimax)アルゴリズムの簡略化されたバージョンです。ここでは、最大探索深度やヒューリスティック評価関数はありません。私はちょうど作った。 – Kevin
実際には、最初にいくつかの数字のGrundy値を知っていれば、それを解決するより良い方法があるので、私は尋ねていました。私は最初の60の自然数についてそれらを知っています。今、ポイントは、(知識を持っている)初期の状況を直接調べることで解決できるということです。だから、私は正確な数式を探しています。それ以外の場合、このメソッドは常にtrueです。とにかく、ありがとう。 – Sushant
関連の任意のヒープを破棄:http://stackoverflow.com/questions/9791406/grundys-game-dividing-a -pile-into-two-unameal-piles – amit
@amitそれは私自身の質問です。しかし、考えてくれてありがとう。 – Sushant
私は知っている、私はそれを投稿しているので、あなたが探している答えを提供する可能性が高いでしょう。 – amit