프로그래머스에서 코딩 테스트를 준비하던 중 PCCP 기출문제라는 문제집이 추가되었길래 풀어보았다. 아직 올라온 지 얼마 되지 않아 관련 글이 많이 없길래 내 풀이를 공유해본다.
정확한 문제 제목은 없이 번호만 써져있지만 굳이 이름을 붙이자면 붕대 감기 라는 이름을 붙일 수 있을 것 같다. 문제 링크는 아래와 같다.
https://school.programmers.co.kr/learn/courses/30/lessons/250137
그냥 게임이 진행되는 시간동안 계속해서 매초마다 필요한 작업들을 경우의 수에 맞춰 진행하면 된다.
0초에는 아무런 일이 일어나지 않기 때문에 1초부터 시작해서 게임이 종료될 때까지 반복문을 돌리는 방식으로 풀었다.
반복문은 조기에 종료될 수도 있고 모든 공격을 마칠 때까지 돌 수도 있다.
반복문이 조기에 종료되는 경우부터 살펴보자. 한 턴(1초)을 돌은 이후에 현재 체력이 0 이하로 떨어지게 되면 모든 공격을 살펴볼 필요 없이 -1 을 반환하며 게임을 종료한다. 매 턴마다 갱신하게 될 현재 체력을 curHealth
라는 이름의 변수로 초기화해서 반복문 한 번을 돌 때마다 0 이하인지 점검해주자.
코드의 일부분만 살펴보자면 다음과 같다.
for (int i = 1; i <= endTime; i++) {
/* 공격 혹은 체력 회복을 진행... */
if (curHealth <= 0) { // 이번 턴을 마치고 체력이 바닥났다면 종료
return -1;
}
}
int[][] attacks
에 담겨있는 공격 정보를 Map 을 이용해 초기화했다. 매 초마다 공격이 있는지 없는지 확인하기 위해 공격시각
을 key로, 피해량
을 value로 저장해뒀다. 그리고 매 초마다 공격 여부를 확인했다.
코드의 일부분만 살펴보자면 다음과 같다.
for (int[] attack : attacks) {
attackInfo.put(attack[0], attack[1]);
endTime = attack[0];
}
for (int i = 1; i <= endTime; i++) {
if (attackInfo.containsKey(i)) { // 공격이 있다면
// 피해량 반영...
} else { // 공격이 없다면
// 체력 회복 반영...
}
if (curHealth <= 0) { // 이번 턴을 마치고 체력이 바닥났다면 종료
return -1;
}
}
이제 공격이 있을 때 피해량 반영과 공격이 없을 때 체력 회복을 하는 부분만 구현을 하면 된다.
공격을 받는 경우부터 살펴보자. 앞서 Map에 초기화해둔 해당 공격의 피해량만큼을 현재 체력에서 빼주면 된다. 이때 함께 해주어야 할 추가적인 작업이 있다. 체력 회복 연속 성공 시간
을 0 으로 갱신해줘야 한다.
이를 코드로 옮기면 다음과 같다.
curHealth -= attackInfo.get(i);
successiveTime = 0;
공격이 없을 때는 체력을 회복하는 작업을 진행해주면 된다.
이때 해주어야 할 작업을 세분화하면 총 4가지다.
초당 회복량
반영추가 회복량
을 현재 체력에 반영위 4가지만을 코드로 보면 다음과 같다.
curHealth += bandage[1]; // 1번 작업
successiveTime++; // 2번 작업
if (successiveTime == bandage[0]) { // 3번 작업
curHealth += bandage[2];
successiveTime = 0;
}
if (curHealth > health) { // 4번 작업
curHealth = health;
}
위의 모든 작업들을 하나로 합친 내가 제출한 전체 코드는 다음과 같다.
import java.util.HashMap;
import java.util.Map;
public class PCCP1번 {
static Map<Integer, Integer> attackInfo = new HashMap<>();
static int endTime = 0;
static int curHealth = 0;
static int successiveTime = 0;
public int solution(int[] bandage, int health, int[][] attacks) {
curHealth = health;
for (int[] attack : attacks) {
attackInfo.put(attack[0], attack[1]);
endTime = attack[0];
}
/* 1초부터 마지막 공격 시각까지 체력 정보 초기화 */
for (int i = 1; i <= endTime; i++) {
if (attackInfo.containsKey(i)) { // 공격이 있다면
curHealth -= attackInfo.get(i);
successiveTime = 0;
} else { // 공격이 없다면
curHealth += bandage[1];
successiveTime++;
if (successiveTime == bandage[0]) {
curHealth += bandage[2];
successiveTime = 0;
}
if (curHealth > health) {
curHealth = health;
}
}
if (curHealth <= 0) { // 이번 턴을 마치고 체력이 바닥났다면 종료
return -1;
}
}
return curHealth;
}
}