어떤 게임에는 붕대 감기라는 기술이 있습니다.
붕대 감기는 t초 동안 붕대를 감으면서 1초마다 x만큼의 체력을 회복합니다. t초 연속으로 붕대를 감는 데 성공한다면 y만큼의 체력을 추가로 회복합니다. 게임 캐릭터에는 최대 체력이 존재해 현재 체력이 최대 체력보다 커지는 것은 불가능합니다.
기술을 쓰는 도중 몬스터에게 공격을 당하면 기술이 취소되고, 공격을 당하는 순간에는 체력을 회복할 수 없습니다. 몬스터에게 공격당해 기술이 취소당하거나 기술이 끝나면 그 즉시 붕대 감기를 다시 사용하며, 연속 성공 시간이 0으로 초기화됩니다.
몬스터의 공격을 받으면 정해진 피해량만큼 현재 체력이 줄어듭니다. 이때, 현재 체력이 0 이하가 되면 캐릭터가 죽으며 더 이상 체력을 회복할 수 없습니다.
당신은 붕대감기 기술의 정보, 캐릭터가 가진 최대 체력과 몬스터의 공격 패턴이 주어질 때 캐릭터가 끝까지 생존할 수 있는지 궁금합니다.
붕대 감기 기술의 시전 시간, 1초당 회복량, 추가 회복량을 담은 1차원 정수 배열 bandage와 최대 체력을 의미하는 정수 health, 몬스터의 공격 시간과 피해량을 담은 2차원 정수 배열 attacks가 매개변수로 주어집니다. 모든 공격이 끝난 직후 남은 체력을 return 하도록 solution 함수를 완성해 주세요. 만약 몬스터의 공격을 받고 캐릭터의 체력이 0 이하가 되어 죽는다면 -1을 return 해주세요.
bandage는 [시전 시간, 초당 회복량, 추가 회복량] 형태의 길이가 3인 정수 배열입니다.
1 ≤ 시전 시간 = t ≤ 50
1 ≤ 초당 회복량 = x ≤ 100
1 ≤ 추가 회복량 = y ≤ 100
1 ≤ health ≤ 1,000
1 ≤ attacks의 길이 ≤ 100
attacks[i]는 [공격 시간, 피해량] 형태의 길이가 2인 정수 배열입니다.
attacks는 공격 시간을 기준으로 오름차순 정렬된 상태입니다.
attacks의 공격 시간은 모두 다릅니다.
1 ≤ 공격 시간 ≤ 1,000
1 ≤ 피해량 ≤ 100
| bandage | health | attacks | result |
|---|---|---|---|
| [5, 1, 5] | 30 | [[2, 10], [9, 15], [10, 5], [11, 5]] | 5 |
| [3, 2, 7] | 20 | [[1, 15], [5, 16], [8, 6]] | -1 |
| [4, 2, 7] | 20 | [[1, 15], [5, 16], [8, 6]] | -1 |
| [1, 1, 1] | 5 | [[1, 2], [3, 2]] | 3 |
풀이
처음 문제를 이해하고 나서 떠올린 풀이는 2개의 리스트를 만들어 체력의 변동을 관리하고 공격 시간과 피해량을 담는 것이었다
공격이 끝나는 시점의 체력을 알아야하기 때문에 attacks의 마지막 원소의 0번째 인덱스+1 길이 만큼 리스트 두개를 생성했다
체력 관리 리스트는 모두 0으로 초기화한 후에 0번째 인덱스만 health로 값을 변경해줬고
공격 시간 리스트는 모두 0으로 초기화한 후에 for 루프를 돌면서 공격 시간에 해당하는 인덱스에 대해서 피해량으로 값을 바꿔줬다
그리고 딱 for 루프를 마지막 공격 시점까지 한 번 돌면서 조건을 분기해줬다
제출했을 때 두 개의 테스트 케이스가 실패해서 다른 풀이를 찾아보니 체력이 0 이하로 떨어지는 순간 바로 -1을 리턴해야한다는 것을 고려하지 않았었다
def solution(bandage, health, attacks):
max_len = attacks[-1][0]
status = [0] * (max_len+1)
status[0] = health
cnt = 0
attack_list = [0]*(max_len+1)
for t, p in attacks:
attack_list[t] = p
for i in range(1,max_len+1):
if attack_list[i] != 0: #공격받음
status[i] = status[i-1] - attack_list[i]
cnt = 0
if status[i] <= 0:
return -1
else: #공격안함
status[i] = min(health, status[i-1] + bandage[1])
cnt += 1
if cnt == bandage[0]:
status[i] = min(health, status[i]+bandage[2])
cnt = 0
if status[-1] <= 0:
return -1
else:
return status[-1]
체력을 회복하는 것에 있어서는 최대 체력 이상으로 회복이 불가능하기 때문에 굳이 if문으로 조건 분기하기보다는 min(health, status[i-1] + bandage[1])를 현재 체력을 계산하는 방식으로 사용했다