ABC119-C Synthetic Kadomatsu

ABCの問題名って読み飛ばしちゃったりすることが多いですが,合成門松!ときました。うん,できない。C問題だから簡単かなと思ったけどよくわからない。こないだ蟻本でやったことを思い出したけどよくわからず。

で,解説を読みました。やはりdfsを使うようでした。でも解説読んでソースを読みますがしばらく意味が分かりませんでした。

   ret0 = dfs(cur+1, a, b, c)
   ret1 = dfs(cur+1, a + l[cur], b, c) + 10
   ret2 = dfs(cur+1, a , b + l[cur], c) + 10
   ret3 = dfs(cur+1, a , b, c + l[cur]) + 10

※retは結果を受け取る変数名としてよく使われる(らしい)resultの略。慣れないしピンとこない。まだresのほうが好き。というかresultじゃだめなの?長いの?

まず,a,b,cは所持している(目標の長さにする途中の)3本の竹の長さです。処理内容は各行で+10されていることからもわかるように,2本の竹を合成する処理です。最初の1行は合成しないとき。基本はこの処理を繰り返します。延長魔法と短縮魔法を使う処理はここです。

    if cur == N:
       return abs(a-A)+abs(b-B)+abs(c-C) - 30 if min(a,b,c)>0 else INF

cur==Nのとき(つまりもう合成する竹がないとき)だけ。abs(a-A)などはあと何cmで目的の長さになるか(つまりあと何回延長魔法を使えばよいか,absにするのは延長でも短縮でも消費MPは同じだから)を表します。それをa,b,cそれぞれに計算します。-30されているのはN>=3だからというのが端的な答えだと思います。あとはmainの処理はこの1行だから

print(dfs(0,0,0,0))

と言っても良いと思います。最初は手持ちの3本の竹の長さはすべて0なので延長魔法を使えません。したがって,必ずret1,ret2,ret3の処理をくぐったあとで延長魔法の処理になります。つまり実際には不要なMP消費+10が3回行われるのです。ちなみに,この処理ですが

if min(a,b,c)>0 else INF

あまり本質的な処理ではありません。min(a,b,c)>0とはa,b,cすべてが0より大きいという意味ですが最終的な結果をみれば必ずそうなっています。しかしdfsの処理の中ではret0の処理だけをN回行うというものも計算されています。そういう場合はMP消費をINFとしておいて答えの候補から外しています。

処理の全文は公式editorialに載っていますのでここには掲載しません。公式の方を参照してください。

この記事が気に入ったらサポートをしてみませんか?