動的計画法で売った次の日は買えない決まりの売り買いの利益を最大にする

毎日の値段の並びで、何回でも売り買いできるが売った次の日は休む決まりのとき、利益の最大を求めます。持っている、今日売った、休んでいるの 3 つの状態を日ごとに持ち歩く練習です。

海外で定番の問題リスト 4 本には入っていません

問題

ある品物の毎日の値段が、並び prices で与えられます。prices[i] は i 日目の値段です。次の決まりで売り買いをするとき、得られる利益のいちばん大きい値を返す関数を書いてください。

  • 1 日に、買うか売るか何もしないかのどれか 1 つだけをします
  • 持てる品物は 1 つまでです。持っている間は買えず、持っていなければ売れません
  • 売った次の日は休みで、買えません (その次の日からは買えます)
  • 売り買いは何回してもかまいません。1 回もしなければ利益は 0 です
  • prices の長さは 1 以上 5000 以下で、どの値段も 0 以上 1000 以下の整数です

入力と出力の例

例 1

0 日目に 4 で買って 1 日目に 9 で売り、2 日目は休みます。3 日目に 2 で買って 4 日目に 7 で売り、5 と 5 で 10 です。

prices = [4, 9, 8, 2, 7]
10

例 2

休みが無ければ 2 で買って 6 で売り、3 で買って 8 で売る 9 ですが、6 で売った次の日の 3 では買えません。2 で買って 8 で売る 6 がいちばん大きくなります。

prices = [2, 6, 3, 8]
6

例 3

値段が下がり続けるので、売り買いしないのがいちばんです。

prices = [9, 7, 4, 1]
0

面接での聞かれ方

面接では、1 回だけ売り買いする株の問題の続きとして、決まりを足して出されます。

  • 「何回でも売り買いできますが、売った翌日は買えません。最大の利益は?」
  • 最初に「同じ日に売って買えますか?」「休みは売った次の 1 日だけですか?」と確かめられるかを見られます
  • 書き終えると「状態の移り方を図で説明してください」と言われることがあります

日ごとに「どの状態にいるか」を決めて、状態の移り方を書き出せるかが見どころです。

ヒント

まだ開いていません

付箋は 4 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

アルゴリズムのチートシートの「動的計画法 (DP)」に、この型の要点を表とコードでまとめています。

動的計画法は、途中の答えを覚えておいて、同じ計算をやり直さない書き方です。漸化式で言い直せる問題が多いです。

main.py
def cooldown_profit(prices: list[int]) -> int:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(cooldown_profit([4, 9, 8, 2, 7]))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します