[프로그래머스] 붕대 감기 (PCCP 기출문제 1번) - 자바 Java

박소은·2024년 6월 22일
0
post-custom-banner

문제

https://school.programmers.co.kr/learn/courses/30/lessons/250137

문제 설명

어떤 게임에는 붕대 감기라는 기술이 있습니다.

붕대 감기는 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

풀이

처음 체력은 최대 체력인 health로 초기화한다.

int answer = health;

2차원 배열로 이루어진 attacks 배열의 [i][0]번째 인덱스에는 몬스터가 공격하는 시간이 담겨 있다. 이를 편의상 Queue에 저장하고 현재 시간과 비교하여 다음 공격 시간에 해당되는지를 확인하려고 한다.

Queue<Integer> queue = new LinkedList<>();

for (int i = 0; i < attacks.length; i++) {
	queue.add(attacks[i][0]);
}

또한 Queue를 통해 다음 공격 시간과 현재 시간을 비교한 결과 일치한다면 정해진 피해량만큼 현재 체력에서 빼주어야 한다. 몬스터 공격 시간에 따른 피해량을 빨리 찾기 위해 Map을 사용하였다.

Map<Integer, Integer> map = new HashMap<>();

for (int i = 0; i < attacks.length; i++) {
	map.put(attacks[i][0], attacks[i][1]);
}

int 형 정수 plus를 통해 연속 성공 시간을 측정하며, 0으로 초기화한다.

int plus = 0;

1초 부터 n초까지를 차례대로 계산해나간다. 몬스터 공격시간이 담겨 있는 queue에서 peek() 메서드를 사용하면 선입선출에 따라 제일 처음 몬스터 공격시간이 반환된다. 만약 지금 시간과 일치한다면 현재 체력이 담겨 있는 answer에서 정해진 피해량을 빼준다. 지금 큐에서 맨앞에 있는 몬스터 공격시간은 제거해주고, 그 다음 몬스터 공격시간이 제일 앞에 올 수 있도록 해준다. 몬스터에게 공격받으면 연속 성공 시간은 0으로 초기화하고, 만약 현재 체력이 0 이하라면 -1을 반환한다.

만약 지금 시간이 queue에서 반환한 몬스터 공격시간과 일치하지 않는다면, 문제의 조건에 맞게 체력을 회복한다.

n초가 되었을 때 남은 현재 체력을 반환한다.

전체 코드

import java.util.*;

class Solution {
    public int solution(int[] bandage, int health, int[][] attacks) {

        int answer = health;

        int n = attacks[attacks.length - 1][0];

        Queue<Integer> queue = new LinkedList<>();

        Map<Integer, Integer> map = new HashMap<>();

        int plus = 0;
        for (int i = 0; i < attacks.length; i++) {
            queue.add(attacks[i][0]);
            map.put(attacks[i][0], attacks[i][1]);
        }


        for (int i = 1; i <= n; i++) {
            if (queue.peek() == i) {
                answer -= map.get(queue.remove());
                plus = 0;
                if (answer <= 0) return -1;
            } else {
                answer += bandage[1];
                plus++;
                if (plus == bandage[0]) {
                    answer += bandage[2];
                    plus = 0;
                }
                if (answer > health) answer = health;
            }
        }


        return answer;
    }
}
profile
Backend Developer
post-custom-banner

0개의 댓글