0
1

More than 3 years have passed since last update.

[Python] 動的計画法 ABC219D

Last updated at Posted at 2021-09-20

ABC219D

動的計画法で解く。

動的計画法による外部設計は次のようになります。

dpの定義:

dp[i][j][k]=(i番目までの弁当で、たこ焼きはj個、たい焼きはk個食べる最小の個数)

dp漸化式の定義:

dp[i+1][j+A_{i+1}][k+B_{i+1}] = min(dp[i][j+A_{i+1}][k+B_{i+1}], dp[i][j][k] + 1)\\
dp[i+1][j][k] =min(dp[i][j][k],dp[i+1][j][k])\\

ただし、$j+A_{i+1}>X$ でこの弁当を購入するとたこ焼きが $X$ 個を超える場合は $j+A_{i+1}$ の代わりに $X$、$k+B_{i+1}>Y$ でたい焼きが $Y$ 個を超える場合は $k+B_{i+1}$ の代わりに $Y$ にします。

dp初期条件:

dp[0][0][0] = 0\\
dp[i][j][k] = ∞

求める解: $dp[N][X][Y]$
最後に $dp[N][X][Y]=∞$ なら、すべての弁当を買っても目標を達成できないので、-1 を出力します。

計算量は、計算量は $O(NXY)$ です。

サンプルコード(PyPy3)
def main():
    INF = 1000
    N = int(input())
    X, Y = map(int, input().split())
    dp = [[[INF] * (Y + 1) for _ in range(X + 1)] for _ in range(N + 1)]

    mat = []
    for _ in range(N):
        a, b = map(int, input().split())
        mat.append((a, b))

    dp[0][0][0] = 0

    for i in range(N):
        x, y = mat[i]
        for j in range(X + 1):
            jj = min(j + x, X)
            for k in range(Y + 1):
                dp[i + 1][j][k] = min(dp[i + 1][j][k], dp[i][j][k])
                kk = min(k + y, Y)
                dp[i + 1][jj][kk] = min(dp[i + 1][jj][kk], dp[i][j][k] + 1)

    print(dp[N][X][Y] if dp[N][X][Y] < INF else -1)


if __name__ == '__main__':
    main()

本番では解法と外部設計までほぼ模範解答出来たのだが、そこまでに時間を掛け過ぎたこともあり、実装する時間が足りなかった。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1