AtCoder Beginner Contest 085 D – Katana Thrower をPython3で解く

Share

AtCoder上にある問題のうち、AtCoder Problemsでdiff 800以上と判定されているものを順番に解いていく企画。
基本的な考え方は全てコード中のコメントに入れてあるので、参照のこと。

出典:
AtCoder Beginner Contest 085 D – Katana Thrower

最終的には、どの刀を投げるかを全探索する問題といえる。しかし、Katana Throwerってそのまんまだよな……。

# AtCoder Beginner Contest 085 D - Katana Thrower
# https://atcoder.jp/contests/abc085/tasks/abc085_d
# tag: 考察 事前ソート 累積和

# 攻撃方法としては、適切な回数振ってから、
# 最後にまとめて投げると仮定する。

# 投げずに振る刀については、振ったときの攻撃力が
# 最大のものを振る以外の意味がない。

# また、投げる刀については、投げたときの攻撃力が
# 最大のものから順番に投げていくことになる。

# 投げる本数は 0 ~ N 本になるので、これを
# 全探索する。

def main():
    N, H = map(int, input().split())
    katanas = [list(map(int, input().split())) for _ in range(N)]

    # 振るときの攻撃力を求める(最大値)
    swings = [k[0] for k in katanas]
    max_swing = max(swings)

    # 投げたときの攻撃力を高い順にソートしておき、
    # 累積和を取っておく
    throws = [k[1] for k in katanas]
    throws.sort(reverse=True)
    csum_throws = [0]
    for d in throws:
        csum_throws.append(csum_throws[-1] + d)
    
    result = 10**9

    # cnt_throw 本投げるとして……
    for cnt_throw in range(N+1):
        tmp_h = H - csum_throws[cnt_throw]

        # 投げた後、体力が残っていれば刀を振る
        # (実際の動作としては振ってから投げることになる)
        if tmp_h > 0:
            tmp_r = cnt_throw + (tmp_h - 1) // max_swing + 1
        
        # 投げた刀だけで倒せる場合は、振る攻撃は不要
        else:
            tmp_r = cnt_throw

        if tmp_r < result:
            result = tmp_r
        
    print(result)

main()
Share

コメントを残す

メールアドレスが公開されることはありません。