본문 바로가기
코딩테스트

[PCCP 기출문제] 1번, 붕대감기 게임

by 우지uz 2023. 11. 29.

 

def solution(bandage, health, attacks):
주어진 변수로는 다음과 같다. 

bandage = [t,x,y]
붕대를 감는 매초마다 x만큼 회복, t초 연속으로 붕대를 감는 데 성공하면
추가로 y만큼 회복한다

health 는 최대 체력을 의미한다.
max_hp = health 로 재정의했다. 

attacks은 [공격시간, 피해량]를 리스트로 받고 있는데
시간순으로 나열되어 있다는 걸 기억하자!
접근하기 쉽도록, 딕셔너리로 받아주었다.

attack_dict = {}
for i in attacks:
    attack_dict[i[0]] = i[1]

attacks = [[1, 2], [3, 2]] 이라고 한다면

attack_dict = {
"1":"2",
"3":"2"
}
로 정의됩니다.

진행 시간은 t 로, 
붕대를 감는 시간은 bandage_sec
정의했습니다.

def solution(bandage, health, attacks):
    # bandage = [t,x,y], health, attacks
    max_hp = health
    last_attack_time = attacks[-1][0]
    print(last_attack_time)
    
    attack_dict = {}
    for i in attacks:
        attack_dict[i[0]] = i[1]
    print(attack_dict)
    
    t=0

    bandage_sec = 0
    while t<=last_attack_time:
        if t in attack_dict:
            health -= attack_dict[t]
            bandage_sec=0

            # 죽으면 -1 리턴
            if health <=0:
                return -1
        else:
            bandage_sec += 1
            if bandage_sec < bandage[0]:
                health += bandage[1]
                if health>max_hp:
                    health = max_hp

            else:
                health = health + bandage[1] + bandage[2]
                if health>max_hp:
                    health = max_hp
                bandage_sec=0

        t+=1
    return health

예시1번의  attacks 리스트는
[[2, 10], [9, 15], [10, 5], [11, 5]]로
2초에 공격10, 9초에 공격15, 10초에 공격 5, 11초에 공격5 으로

뒤로 가면 갈수록, 시간이 늘어나고 있고 
마지막 공격이 11입니다. 그렇기 때문에 

마지막 공격 시간이 마지막 리스트에 있기 때문에 

    last_attack_time = attacks[-1][0]
마지막 리스트 [-1]에서 [0]은 11초를 의미한다.

 

개선된 코드

def solution(bandage, health, attacks):
    max_hp = health
    last_attack_time = attacks[-1][0]
    
    attack_dict = {time: damage for time, damage in attacks}

    t = 0
    bandage_sec = 0

    while t <= last_attack_time:
        if t in attack_dict:
            health -= attack_dict[t]
            bandage_sec = 0

            # 죽으면 -1 리턴
            if health <= 0:
                return -1
        else:
            bandage_sec += 1
            if bandage_sec < bandage[0]:
                health = min(health + bandage[1], max_hp)
            else:
                health = min(health + bandage[1] + bandage[2], max_hp)
                bandage_sec = 0

        t += 1

    return health

공격에 대한 리스트를, 딕셔너리로 받는 코드가 

attack_dict = {}
    for i in attacks:
        attack_dict[i[0]] = i[1]

이었는데, 간단하게 

attack_dict = {time: damage for time, damage in attacks}

이렇게 받을 수 있다. 

리스트딕셔너리로 변환할때, 가독성과 간결함을 둘다 챙길 수 있었다.
for문을 최대한 사용하지 않는 것도 알고리즘에 도움이 될 것이다. 

 

else 이후에 코드를 

else:
    # 붕대 감기 기술 시전 중인 상황
    bandage_sec += 1  # 시간을 1초 증가

    if bandage_sec < bandage[0]:
        # 아직 기술 시전 시간이 다 차지 않은 경우
        # 1초마다 x만큼의 체력을 회복하고, 최대 체력을 초과하지 않도록 조정
        health = min(health + bandage[1], max_hp)
    else:
        # 기술 시전 시간이 다 찬 경우
        # t초 동안 붕대를 감으면서 1초마다 x만큼의 체력을 회복하고, 추가로 y만큼의 체력을 회복
        # 최대 체력을 초과하지 않도록 조정
        health = min(health + bandage[1] + bandage[2], max_hp)
        bandage_sec = 0  # 붕대 감기 기술의 연속 성공 시간 초기화

t 초가 되지 않았을 때와, t 초가 되었을때의 if/else 로 나뉘었고

min 함수를 통해서, 붕대 감기 회복 시

최대 체력 max_hp 를 넘지 않도록 처리했다.