SRM574 275
問題
0を含まない整数AとBがあり、交互に各ターンでそれぞれ以下の2つの操作ができる。
・いまの数字をreverseする(123->321)
・いまの数字/10する(123->12)
2人でそれぞれの数字を操作していくゲームを考える。
このとき、AがBと同じ数字にすることができたらAの勝ち、できなければBの勝ちとなる。
ターン数は1000ターンよりかかってしまう場合はBの勝ちとなる。
互いに最善の操作でゲームを行った時に、どちらが勝つか?
考え方
AとBのとりうる状態は実は多くない。
なので、実際にturnとAとBをメモ化しながら再帰でシミュレーションしてもできる。
最善というのは、今Aならば、どちらかの操作でBが逃げ切れないような手があれば、勝てる。
今Bならば、どちらかの操作でAが必ず勝つ手ががなければ、勝てる。
シンプルな回答は、文字列とみなして、Aの部分文字列にBまたはBのreverseの文字列が含まれるか否かで判定できる。
もし、Bの方がAより長ければ、reverseしつづければBが勝てる。
AとBが同じ長さならば、同じ文字列かreverse文字列でない限り、Aが1文字でもけずれば上記と同じでBが勝てる。
Bの方がAより短い時、部分文字列として含まれる場合、AはBと同じ文字列にするように操作していけば、Bを短くしたとしても同様に繰り返せるので、かならず勝てる。(1000ターンもいらない)
反省
なんか以下のようなひどいコードを書いていたら、挙動が変わってしまっていた。
探索の仕方がよくないようだった。
//ダメ bool f = false; if(!solve(1)){ f = true; } if(!solve(2)){ f = true; } if(f){ hoge; } //通った if(!solve(1) || !solve(2)){ //solve(2)は!solve(1)がtrueなら呼ばれない hoge; }