Algorithm

[백준][python]16434 드래곤앤던전

soduddl1 2023. 9. 6. 12:27

문제

https://www.acmicpc.net/problem/16434

소스코드

import sys
import math

if __name__ == "__main__":
    n,atk = map(int,input().split())
    room = [list(map(int,sys.stdin.readline().split())) for _ in range(n)]

    max_hp = 0
    l,r = 1, sys.maxsize

    while l <= r:
        mid = (l+r) // 2

        cur_hp = mid
        cur_atk = atk

        for ro in room:
            t,a,h = ro
            if t == 1:
                cur_hp -= (math.ceil(h / cur_atk) - 1) * a
                if cur_hp <= 0:
                    break

            elif t == 2:
                cur_atk += a
                cur_hp = min(mid, cur_hp+h)

            if cur_hp <= 0:
                break

        if cur_hp <= 0 : #용사가 죽었으면 생명력 높이기
            l = mid + 1
        else:  #용사가 살았으면 생명력 낮추기
            r = mid - 1
            max_hp = mid

    print(max_hp)

설명

이분탐색으로 최대 HP를 구하는 문제이다.

몬스터와 전투를 하는 부분을 while 문으로 구현하게 되면 시간초과가 발생한다.

전투 과정을 경우의 수로 정의해서 구현하면 시간초과 문제를 해결할 수 있다.

 

                cur_hp -= (math.ceil(h / cur_atk) - 1) * a
                if cur_hp <= 0:
                    break

몬스터가 죽는 경우는 상관없기 때문에 구하지 않아도 된다.

중간에 누가 죽어서 break되는 부분을 생각하지 않고 전투 전체를 놓고 최종 결과만 생각한다.

 

(몬스터의 체력 / 용사의 공격력) 에서 올림 처리를 해주면 총 용사가 공격하는 횟수이다. 

  • 만약 몬스터 체력이 10이고 용사의 공격력이 3이면 3.5 회 공격하는데 이는 4회 공격하는거랑 같다.

여기서 1을 빼주면 몬스터가 용사를 공격하는 횟수가 된다. 

  • 용사가 먼저 공격을 하기 때문이다.
  • 몬스터와 용사가 체력과 공격력이 동일하다고 가정하면, 몬스터가 먼저 죽기 때문에 용사는 -1 번을 뺀 공격을 받게 된다

몬스터가 공격할 횟수에서 몬스터의 공격력을 곱해주고 용사의 체력에서 빼면 전투를 마친 용사의 체력을 구할 수 있다.

몬스터가 더 쎈 경우는? 은 굳이 생각할 필요없다 그러면 마이너스 체력이 나오기 때문에 생각하지 않아도 된다.

그럼 몬스터의 체력이 마이너스가 나오는 경우는? 상관없다 용사의 체력이 마이너스인지 아닌지가 궁금한 사항이다.

 

또 이분탐색을 할 때 r 값을 최대한 크게 해줘야 모든 경우의 수를 다 포함해서 계산할 수 있다.