読者です 読者をやめる 読者になる 読者になる

土下座しながら探索中

主に競技プログラミング

AOJ 1230 : Nim

AOJ ゲーム木

問題リンク:Nim | Aizu Online Judge

解法:

実際にゲーム木をみていく
memo[i][j] := 人i に山の残りがjの状態できたときの勝敗
としてメモ化した
自分のチーム基準で結果のブール型をリターンする
山が残り1枚以下になった時、
 自分のチームのターンなら return false; <= 負け
相手のチームのターンなら return true ; <= 勝ち

ループで山を1枚から指定された枚数まで全て試す
 自分のチームのターンなら、リターンされた結果に1つでもtrue(勝利)があれば return true
相手のチームのターンなら、リターンされた結果に1つでもfalse(負け)があれば return false

コードーーーーーーーー

int n,S;
short M[21];
short memo[21][MAX];
 
bool dfs(int phase,int nS)
{
  if(memo[phase%(2*n)][nS] != -1)return memo[phase%(2*n)][nS];
  if(nS <= 1)
    {
      if(phase%2)return 1;//enemy
      else       return 0;//friend
    }
 
  bool res,update;
  update = false;
  REP(i,1,M[phase%(2*n)]+1)
    {
      bool bres = dfs(phase+1,nS-i);
      if(phase%2)
    {
      if(!update)
        {
          update = true;
          res = bres;
        } 
      else res &= bres; 
    }
      else
    {
      if(!update)
        {
          update = true;
          res = bres;
        }
      else res |= bres;
    }
    }
  return memo[phase%(2*n)][nS] = res;
}
 
int main()
{
  while(cin >> n,n)
    {
      cin >> S;
      rep(i,2*n)cin >> M[i];
      rep(i,21)rep(j,MAX)memo[i][j] = -1;
      //cout << "---------" <<endl;
      cout << (dfs(0,S)?1:0) << endl;
    }
  return 0;
}