必勝法

A multiplication game
http://acm.uva.es/p/v8/847.html

p=1から始めて,スタン,オリーが交互に2から9の好きな数字をかけて,先にnに達した方が勝ちというゲームがある.nが与えられたときに,どちらが勝つかを求める問題.二人とも最善の手を採ることが保障されている.

この手の問題は正直苦手なんだけど,この問題は割と簡単.二人とも,とにかくnに達したいわけだから,大きな数字をどんどんかけていく.一方で,相手がnに達してしまうと負けになるのだから,小さな数字をかけるという戦略もある.つまり,攻めの場合と守りの場合に分けて考えれば良い.2から9まで選べるけれど,実際には2と9しか考えない.

プログラムは次のようになる.

while(true) {
  // Stan's turn
  pStan *= 9;
  pOllie *= 2;

  if(pStan >= n) {
    cout << "Stan wins." << endl;
    break;
  }

  // Ollie's turn
  pStan *= 2;
  pOllie *= 9;

  if(pOllie >= n) {
    cout << "Ollie wins." << endl;
    break;
  }
}

スタンのターンとオリーのターンそれぞれにおいて,pStanはスタンが攻めている場合のp,pOllieはオリーが攻めている場合のpである.nに達するのが目的なのだから,自分はひたすらnに達するように,相手に対してはひたすらnに達しないようにするしかない.2つの場合を同時にシミュレートすると,結果論だけど先にnに達した方の戦略が良かったってことになる.