AT274の技術だったりなかったり

あっとのTECH LOG

競プロのこととか技術のこととか。たまに日常を書きます。

ABC153 E - Crested Ibis vs Monster

問題原文

atcoder.jp

問題要旨

体力が  H のモンスターがいる。
 N 種類の魔法が使えて、魔法  i は、モンスターの体力を  A_i 減らすことができるが、 魔力を  B_i 消費する。
同じ魔法を何度でも使える時、モンスターの体力を0以下にするためには、最小でどのぐらいの魔力がいるか?

  •    1 \leq H \leq 10^{4}
  •    1 \leq N \leq 10^{3}
  •    1 \leq A_i \leq 10^{4}
  •    1 \leq B_i \leq 10^{4}

解法

どう考えてもDPの雰囲気しかしない。というかDPド典型。
 dp[damage\rbrack  = モンスターに damege 分のダメージを与えるために必要な最小魔力 として、あとは個数制限なしナップサックと同じ。
計算量は  O(NH)。ステップ数が  10^{7} 程度になってちょっとビクっとするけど流石に余裕で通る。

実装

 H を超える部分はまとめてあげると楽。

Magic = [list(map(int, input().split())) for i in range(N)]
MAX_COST = max(Magic)[1]
 
# dp[damage] := モンスターに damage を与えるために必要な最小コスト
dp = [float('inf')] * (H + 1)
dp[0] = 0
for h in range(H):
    for damage, cost in Magic:
        next_index = min(h + damage, H)
        dp[next_index] = min(dp[next_index], dp[h] + cost)
 
print(dp[-1])

感想

瞬殺できてよかった。
DPの基礎問としてちょうどいいかも。