ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 프로그래머스 [PCCP 기출문제] 1번 / <붕대 감기>
    Algorithms 2026. 2. 1. 15:18

    문제 이해

    게임에 붕대 감기라는 기술이 있다.

    • t초 동안 붕대를 감는다.
    • 붕대를 감는 동안 매 초 x 만큼 회복한다.
    • t초 연속 성공하면 그 순간 추가로 y 만큼 회복한다.
    • 최대 체력(maxHealth)을 넘을 수 없다.
    • 공격을 받는 순간 기술은 취소되고, 그 순간에는 회복이 불가능하다.
    • 공격으로 취소되거나 기술이 끝나면 즉시 다시 붕대 감기를 사용하고, 연속 성공 시간은 0으로 초기화된다.
    • 체력이 0 이하가 되면 즉시 죽어서 -1을 반환한다.

     

    변수 제한사항은 다음과 같다

    • 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

     

    입출력 예

     

     

     


     

    초기 접근

    공격 패턴 attacks의 마지막 공격 시간이 전체 시뮬레이션의 끝이므로

    • lastTime = attacks[attacks.length - 1][0]
    • 1초부터 lastTime까지 매초 시뮬레이션한다.

    매초마다

    1. 공격이 있으면 피해를 받고 연속 성공 시간 초기화
    2. 공격이 없으면 회복 + 연속 성공 시간 증가
    3. t초 연속이면 보너스 회복
    4. 최대 체력 처리
    5. 0 이하면 즉시 종료

    또한 attacks를 매초마다 선형 탐색하면 시간이 낭비라서 (공격 시간 -> 피해량) 형태로 HashMap에 담아 O(1)로 조회했다.

     

     


     

    내가 겪었던 시행착오

    구현 문제는 한 줄 차이로 계속 틀릴 때가 많았는데 이 문제도 딱 그랬다.

    자동완성에 익숙해져서 간단한 문법 오류가 많은데, 이 부분은 확실히 연습이 필요하다.

     

    1) if (attackMap.get(i))는 왜 안 되지?

    if (attackMap.get(i)) { ... }

     

    get(i)는 Integer를 반환한다. 하지만 if() 조건식은 boolean만 받을 수 있다.

    그래서 공격 여부는 다음과 같이 체크해야 한다.

    if (attackMap.get(i) != null) { ... }
    // 또는
    if (attackMap.containsKey(i)) { ... }

     

     

    2) 가장 크게 틀렸던 포인트: 보너스 회복 타이밍

    여기서부터가 진짜 핵심 시행착오였다.

     

    처음 구현에서 t초 연속 성공을 %로 처리하면서, 어느 순간 기준이 꼬였다.

    특히 t=1일 때 문제가 바로 드러났는데, 예를 들어 [1,1,1], health=5, attacks=[[1,2],[3,2]] 케이스에서

    • 2초에 회복을 해야 하는데, 보너스가 걸리는 순간에 x 회복을 빼먹거나
    • 연속 시간(cycle)을 한 초에 두 번 올려서 다음 초부터 카운트가 틀어지는 문제가 생겼다.

    따라서 결론은 다음과 같다.

    회복하는 초에는 무조건 초당 회복량을 회복하고, 그 초가 t번째 연속이라면 추가회복량을 추가로 회복한다.

    즉 t번째 초는 초당 회복량 + 추가회복량가 들어가야 한다. 따라서 초에 상단에 초당 회복량을 무조건 회복하도록 처리하고 조건에 따라 추가 회복량을 처리했다. 

     


     

    최종 제출 코드

    최종적으로는 아래처럼 구현했고 모든 테스트를 통과했다.

    import java.util.*;
    
    class Solution {
        public int solution(int[] bandage, int health, int[][] attacks) {
            int lastTime = attacks[attacks.length - 1][0];
            int maxHealth = health;
            int cycle = 0;
    
            HashMap<Integer, Integer> attackMap = new HashMap<>();
            for (int i = 0; i < attacks.length; i++) {
                attackMap.put(attacks[i][0], attacks[i][1]);
            }
    
            for (int i = 1; i <= lastTime; i++) {
                if (attackMap.get(i) != null) {
                    health -= attackMap.get(i);
                    cycle = 0;
                    if (health <= 0) return -1;
                } else {
                    health += bandage[1]; // 초당 회복량
                    cycle++;
    
                    if (cycle % bandage[0] == 0) { // t초 연속 성공
                        health += bandage[2];      // 추가 회복량
                    }
    
                    if (maxHealth < health) {
                        health = maxHealth;
                    }
                }
            }
            return health;
        }
    }

     


     

    느낀점

    이 문제는 구현 자체의 난이도는 높지 않았지만,
    연속 성공 시간과 회복이 적용되는 초의 기준이 조금만 어긋나도 바로 오답으로 이어질 수 있는 문제였다.
    특히 보너스 회복이 적용되는 타이밍을 정확히 이해하지 못하면, 일부 테스트 케이스에서 쉽게 틀릴 수 있었다.

     

    직전 문제를 풀면서 사용했던 것처럼
    HashMap을 이용해 공격 시간을 미리 정리하고 전체 순회를 한 번만으로 처리한 접근은 비교적 잘한 선택이었다고 생각한다.

     

    다만 구현 과정에서 변수의 의미가 명확하지 않거나, 자바 문법에 익숙하지 않아 불필요한 시행착오가 발생한 점은 아쉬웠다.

    앞으로는 변수명과 로직의 역할을 더 명확히 구분하고, 자동 완성에 의존하지 않고도 자바 문법을 자연스럽게 떠올릴 수 있도록 꾸준히 연습할 필요가 있겠다고 느꼈다.

     

     

Designed by Tistory.