[BOJ] 백준 16434번 드래곤 앤 던전 (Python)

deannn.Park·2021년 7월 20일
0

BOJ - 백준

목록 보기
25/42
post-thumbnail

문제

용사는 공주를 구하기 위해 무시무시한 용이 있는 던전으로 향하기로 하였습니다. 우선 용사는 용사 자신과 던전을 분석하였습니다.

용사에게는 세 종류의 능력치가 있습니다.

  • H_MaxHP : 용사의 최대 생명력입니다. 이 값은 1이상이어야 하며 던전에 들어간 이후로 변하지 않습니다.
  • H_CurHP : 현재 용사의 생명력입니다. 던전에 들어가기 전 이 값은 용사의 최대 생명력 HMaxHP와 같습니다. 이 값은 HMaxHP보다 커질 수 없습니다.
  • H_ATK : 용사의 공격력입니다.

던전은 총 N개의 방으로 이루어져 있고 i번째 방을 통해서만 i+1번째 방으로 이동 할 수 있습니다. 방에는 포션이 있거나 몬스터가 있는데 몬스터가 있을 경우 몬스터를 쓰러트려야지 다음방으로 이동 할 수 있습니다. N번째 방에는 공주와 용이 있고, 용을 무찌르면 공주를 구할 수 있습니다.

몬스터가 있는 방에 올 경우 다음과 같이 전투가 진행됩니다.

  1. 용사의 공격력 HATK만큼 몬스터의 생명력을 깎습니다.
  2. 몬스터의 생명력이 0 이하이면 전투가 종료되고 용사는 다음 방으로 이동합니다.
  3. 몬스터의 공격력만큼 용사의 생명력 HCurHP를 깎습니다.
  4. 용사의 생명력이 0 이하이면 전투가 종료되고 용사는 사망합니다.
  5. 다시 1부터 진행합니다.

포션이 있는 방에 올 경우 포션을 마셔서 현재 용사의 생명력 HCurHP가 일정량 회복되고 공격력 HATK도 일정량만큼 증가됩니다. 회복된 생명력이 최대 생명력 HMaxHP보다 큰 경우 용사의 현재 생명력 HCurHP가 최대 생명력 HMaxHP와 같아집니다.

용사는 던전으로 향하기 전에 만반의 준비를 하고 있습니다. 용사는 수련을 하면 최대 생명력 HMaxHP를 늘릴 수 있는데 얼마나 수련해야 할지 고민입니다.

용사는 N번 방에 있는 용을 쓰러트리기 위한 최소의 HMaxHP를 여러분이 계산해주면 좋겠다고 합니다.

입력

  • 첫 번째 줄에 방의 개수 N (1 ≤ N ≤ 123,456) 과 용사의 초기 공격력 HATK (1 ≤ H_ATK ≤ 1,000,000) 가 주어집니다.
  • i+1번째 줄엔 i번째 방의 정보를 나타내는 세개의 정수 tᵢ, aᵢ, hᵢ (tᵢ ∈ {1, 2}, 1 ≤ aᵢ, hᵢ ≤ 1,000,000) 가 주어집니다.
  • tᵢ가 1인 경우 공격력이 aᵢ이고 생명력이 hᵢ인 몬스터가 있음을 나타내고, tᵢ가 2인 경우 용사의 공격력 H_ATK를 aᵢ만큼 증가시켜주고 용사의 현재 생명력 H_CurHP를 hᵢ만큼 회복시켜주는 포션이 있음을 나타냅니다.

출력

  • 용사가 N번째 방에 있는 용을 쓰러트리기 위한 최소의 HMaxHP를 출력합니다.

예제

입력 1

3 3
1 1 20
2 3 10
1 3 100

출력 1

49

입력 2

1 1
1 1000000 1000000

출력 2

999999000001

풀이

import math

N, H = map(int, input().split())
dungeons = [list(map(int, input().split())) for _ in range(N)]
lt = 1
rt = 1
for t, a, h in dungeons:	# 총 받는 데미지의 합을 rt로 정함
    if t == 1:
        rt += math.ceil(h / H) * a

rst = 0				# 결과 담을 변수
while lt <= rt:			# 이분탐색 시작
    mid = (lt + rt) // 2	# mid 정의. 초기 생명력

    attack = H			# 현재 공격력과 생명력
    hp = mid
    for t, a, h in dungeons:
        if t == 1:		# 몬스터 있는 경우
            # 싸우는 횟수.
            numOfFight = min(math.ceil(h / attack), math.ceil(hp / a))
            # 싸운 만큼 서로의 생명력 깎음.
            h -= numOfFight * attack
            hp -= numOfFight * a

			# 용사가 이긴 경우
            if h <= 0:
                # 용사가 먼저 때리기에 이겼으면 마지막에는 생명력이 깎일 일이 없으므로 다시 회복
                hp += a
                continue
            # 용사가 진 경우
            if hp <= 0:
                break
                
        else:			# 몬스터가 아닌 포션이 있는 경우
            attack += a		# 공격력 증가
            hp += h		# 생명력 회복
            if hp > mid:	# 회복된 생명력이 최대 생명력보다 크면
                hp = mid	# 최대 생명력에 맞춤

    else:			# 용사가 무사히 모두 무찌른 경우
        rt = mid - 1		# 생명력이 남기에 rt값을 줄임
        rst = mid		# 값 저장

    if hp <= 0:			# 용사가 죽은 경우
        lt = mid + 1		# 생명력이 부족하기에 lt값 키움

print(rst)
profile
컴퓨터 관련 여러 분야 공부중

0개의 댓글