1. 문제 정보

- 출처: 프로그래머스 PCCP 기출문제 1번 / 붕대 감기
- 난이도: Level 1
- 분류: 구현 (Implementation), 시뮬레이션 (Simulation)
2. 문제 설명
어떤 게임 캐릭터가 붕대 감기 기술을 사용하여 체력을 회복하며, 동시에 몬스터의 공격 조건 속에서 생존해야 하는 문제다.
- 붕대 감기 기술:
- t초 동안 붕대를 감으며, 1초마다 x만큼 체력을 회복한다.
- t초 연속으로 성공하면 y만큼의 추가 체력을 더 회복한다.
- 최대 체력 한계를 넘어서 회복하는 것은 불가능하다.
- 몬스터의 공격과 취소 조건:
- 기술을 쓰는 도중 몬스터에게 공격당하면 기술이 강제로 취소된다.
- 공격받는 순간에는 체력을 회복할 수 없으며, 연속 성공 시간이 0으로 리셋된다.
- 공격당한 직후에는 곧바로 다시 붕대 감기를 시작한다.
- 캐릭터의 체력이 0 이하가 되면 사망하며, 게임이 즉시 종료된다.
붕대 감기 기술 정보 bandage, 최대 체력 health, 몬스터의 공격 시간과 피해량을 담은 2차원 배열 attacks가 주어질 때 모든 공격이 끝난 뒤 남은 체력을 구해야 한다. (사망 시 -1 반환)
제한사항
- bandage =$$시전 시간 t, 초당 회복량 x, 추가 회복량 y$$(길이 3인 배열)
- 1 <= t, x, y <= 100
- 최대 체력 health <= 1,000
- 몬스터 공격 횟수 attacks의 길이 <= 100
- 공격 시간은 최대 1,000 이하이며 오름차순 정렬되어 있음
3. 풀이 전략
이 문제는 1초 단위로 루프를 돌며 상태를 변화시키는 시뮬레이션으로도 통과가 가능하다. 공격의 최대 시간이 1,000초로 매우 작기 때문이다.
하지만, "공격과 공격 사이의 평화 시간(Period)"을 계산하여 수학적으로 한 번에 체력을 정산하면, 공격 횟수(최대 100번)만큼만 루프를 도는 극강의 O(N) 효율성을 보장하는 코드를 작성할 수 있다.
💡 수학적 상태 전이 공식 도출하기
몬스터의 이전 공격 시간을 prev, 현재 공격 시간을 time이라고 하자. 그렇다면 두 공격 사이에서 캐릭터가 아무런 방해 없이 온전히 붕대를 감을 수 있는 시간인 평화 시간(period)은 다음과 같다.
평화 시간(Period) 계산식: > period = 현재 공격 시간 - 이전 공격 시간 - 1
이 평화 시간 동안 캐릭터는 정상적으로 붕대를 감아 기본 회복량과 연속 성공 보너스를 얻을 수 있다.
- 기본 회복량: period * 초당 회복량(bandage[1])
- 연속 성공 보너스 횟수: period / 시전 시간(bandage[0]) (정수 나눗셈의 몫)
- 추가 회복량: 보너스 횟수 * 추가 회복량(bandage[2])
따라서 평화 시간 동안 회복되는 최종 체력은 다음과 같다.
최종 체력 변화식: > health = Math.min(현재 체력 + 기본 회복량 + 추가 회복량, 최대 체력)
이후 몬스터의 공격 피해량(damage)을 체력에서 깎아주고, 체력이 0 이하가 되어 사망하는지 판별한다. 마지막으로 prev 시간을 현재 공격 시간(time)으로 업데이트하여 다음 공격 주기로 넘어간다.
4. 정답 코드 (Java)
class Solution {
public int solution(int[] bandage, int health, int[][] attacks) {
int n = attacks.length; // 몬스터의 총 공격 횟수
int prev = 0; // 이전 공격 시각 (초기값 0초)
int max = health; // 최대 체력 한계치 고정
for (int i = 0; i < n; i++) {
int time = attacks[i][0]; // 현재 공격 시각
int damage = attacks[i][1]; // 현재 공격 피해량
// 1. 공격 간의 간격(평화 시간) 계산
int period = time - prev - 1;
// 2. 평화 시간이 0보다 클 때만 자가 회복 진행
if (period > 0) {
// 연속 성공 횟수에 따른 보너스 힐 횟수 계산 (정수 나눗셈 몫 활용)
int bonusCount = period / bandage[0];
int totalHeal = (period * bandage[1]) + (bonusCount * bandage[2]);
// 최대 체력을 넘지 못하도록 한계 설정
health = Math.min(health + totalHeal, max);
}
// 3. 몬스터 공격으로 인한 체력 감소
health -= damage;
prev = time; // 이전 공격 시간을 현재 시간으로 백업
// 4. 즉시 사망 여부 확인 (조기 종료 조건)
if (health <= 0) return -1;
}
return health;
}
}
5. 핵심 포인트
① Period(평화 시간) 공식의 정합성 검증
이전 공격이 2초에 발생했고, 현재 공격이 9초에 발생했다고 해보자. 캐릭터가 안전하게 붕대를 감을 수 있는 시각은 3초, 4초, 5초, 6초, 7초, 8초로 총 6초다. 수식에 대입해 보면 9 - 2 - 1 = 6으로 정확히 맞아떨어짐을 확인할 수 있다. 만약 두 공격이 연속해서 들어와 평화 시간이 존재하지 않는다면(period = 0), 회복 로직을 안전하게 우회하도록 설계했다.
② 몫 연산자를 이용한 보너스 횟수 산출
연속해서 붕대 감기에 성공한 횟수는 평화 시간 period를 기술 시전 시간 bandage[0]으로 나눈 몫으로 매우 심플하게 구해진다. 별도의 누적 카운터 변수를 두고 매 초마다 검사할 필요가 없어 연산 횟수가 획기적으로 줄어든다.
③ 꼼꼼한 예외 처리 (사망 조건)
체력 회복은 항상 최대 체력(max) 한도 내에서만 이루어져야 하므로 Math.min()을 통한 바운더리 처리가 필수다. 또한, 몬스터의 공격을 받은 직후 health <= 0 검사를 진행해 죽었을 경우 지체 없이 -1을 리턴하여 불필요한 다음 연산을 차단하는 최적화 장치를 마련했다.
마치며
이번 문제는 시뮬레이션 유형이지만 매 초마다 상태를 확인하는 무식한 방법 대신, 이벤트(공격) 발생 시점 간의 간격을 활용하여 단숨에 최종 수치를 정산하는 수학적 관점을 키우기에 좋은 문제였다.
#프로그래머스 #PCCP #PCCP기출문제 #붕대감기 #시뮬레이션 #구현 #Java #코딩테스트 #알고리즘 #Simulation
'코딩테스트 > 프로그래머스' 카테고리의 다른 글
| [Java][프로그래머스][PCCP 기출 문제][Level 2] 퍼즐 게임 챌린지 (0) | 2026.05.22 |
|---|---|
| [Java][프로그래머스][알고리즘 고득점 Kit][Level 3] 베스트앨범 (0) | 2026.05.04 |
| [JAVA][2025 프로그래머스 코드챌린지 1차 예선] 지게차와 크레인 (0) | 2026.03.14 |