金沢大会WEB予選問題D
http://ccserv.adm.ehime-u.ac.jp/ICPC/problems/domestic/d2002/problems/D.html
今日、コーチを引き受けているチーム(といっても、私はチームの登録をしただけで指導とかは何もしてない)から、実行効率の良いアルゴリズムについてのアイディアはないかという質問を受けたので、1年ぶりにACM関連の問題についてまじめに取り組んでみる。
問題の内容は、0〜9までの数字を使って、ヒット&ブローをやるとき、トライした数列に関するヒットとブローの数から、正しい答えを推測するプログラムを書けというもの。
問題の桁数と、トライした回数、トライした数列とそのときのヒット&ブローの数が入力として与えられる。そして、そのヒントから推測される答えを出力する。このとき、答えが1つに絞りきれない場合はNOを出力する。
単純な全探査アルゴリズムは、全部の順列を生成しながら、すべてのトライした数列とのヒットとブローの数を求めて、これが入力のヒットとブローの数と一致しているかをしらべる。すべて一致していた場合、その数列は推測される答えとなる。
これは、最大10! = 3628800個の数列を調べなければならず、とにかく実行時間が掛かる。私のノートPCで実際に動かしてみたところ(centrino1.3GHz)、データセット1を解くのに40秒、データセット2を解くのに48秒かかった。これではちと時間がかかりすぎて、恥ずかしい。
さて、全部の順列について調べつくす全探査では効率が悪すぎるので、数列生成途中でヒントと照らし合わせるという枝狩りを仕込んでみた。すると、データセット1、データセット2とも3秒掛からない時間で解くことができた。
ま、こんなもんか。
#includestruct a { char word[11]; int usage[11]; int hit; int blow; } hints[100]; int size, num; int update( char lastanswer[ ], char current[ ], int usage[ ], int index ) { int i, flag=0; int ans = 0; for( i=0; i 1 ) return ans; for( i=0; i 1 ) break; } } else { /* 順列生成が完了したら、正しいかどうかを調べる */ for( i=0; i
ようわからんけど、正しくHTML表示されないなあ。