キーエンスプログラミングコンテスト 2021 E - Greedy Ant に関する記事です.

問題へのリンク

https://atcoder.jp/contests/keyence2021/tasks/keyence2021

解法

公式解説 の通りではありますが,若干表現を変えます.

すぬけ君が,蟻から遠い飴を取っても,蟻の行動には直ちには影響を与えません. そういう状況ではすぬけ君は「スキップ」することにして,後から蟻がその飴に近づいてきたとき (左右いずれかで蟻の最も近い飴になったとき) に取ることにしても,ゲームの意味が変わりません. つまり,次のようにゲームを言い変えることができます. (両端などの扱いはサボっています)

初期化:              // 蟻の初期位置を 2n + 1 とする.
    l := n           // 蟻に最も近い左の飴の位置が 2l
    r := n + 1       // 蟻に最も近い右の飴の位置が 2r
    k := 0           // すぬけ君の「スキップ」回数
ループ:
    k += 1
    while k > 0:
        match すぬけ君の選択():
            case なし: break
            case 左: すぬけ君が 2l の飴を取る; l -= 1
            case 右: すぬけ君が 2r の飴を取る; r += 1
        k -= 1
    蟻が,2l, 2r の飴のおいしい方を取る
    取った方に応じて l -= 1 または r += 1

そこで, f(l,r,k) を,「上記 while の先頭位置で,l,r,k がこの値である時に,すぬけ君がこのあと取る得点の最大値」として 定義します. 次の漸化式が書けます.

f(l, r, k) = max( none(l, r, k)
                , a[l] + f(l - 1, r, k - 1)
                , a[r] + f(l, r + 1, k - 1)
                )
ただし,a[l] > a[r] のとき,none(l, r, k) = f(l - 1, r, k + 1)
そうでないとき,            none(l, r, k) = f(l, r + 1, k + 1)

f(n, n + 1, 1) が求める答です. fは,メモ化再帰で計算でき,時間計算量は O(N^3)です.

経緯

コンテスト中も解けず,復習でも答を思い出せませんでした.blogに書くことで覚えられるか???