프로그래머스 L1 - 붕대 감기

2024. 3. 19. 10:42알고리즘/프로그래머스

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

해석

타임라인을 만들어 공격받는 시간인지 공격을 받지 않는 시간인지 구분한다.

그리고 공격받는 시간이라면 피를 깎고, 그렇지 않으면 회복한다.

단, 피가 가득 찼을 경우에는 회복하지 않아야하고, 연속적으로 회복했을 때 보너스로 받는 회복량이 존재한다.

 

코드

function solution(bandage, health, attacks) {
    var answer = health;
    let max = -1;
    let cnt = 0;
    let attackedTime = new Map(attacks);
    attacks.forEach(([s,m])=> max = Math.max(max,s));
    let timeLine = Array.from({length:max+1}).fill(health);
    for(let i = 1; i<=max;i++){
        if(!attackedTime.has(i)){
            if(answer === health) {
                cnt = 0;
                continue;
            }
            if(answer <= health - bandage[1]) {
                answer += bandage[1];
                cnt++;
            } else {
                answer += health - answer;
                cnt = 0;
            }
            if(cnt===bandage[0]){
                if(health-answer>=bandage[2]) answer+=bandage[2];
                else if(health-answer<bandage[2]&&health-answer>0) answer+=health-answer;
                cnt=0;
            }
        }
        if(attackedTime.has(i)){
            answer -= attackedTime.get(i);
            cnt = 0;
        }
        if(answer<=0) return -1;
    }
    return answer;
}

만일 특정 시간에 공격을 받았으면 데미지만큼 피를 깎는다.

그렇지 않으면 피가 가득 찼는지 아닌지를 판단한다. 가득 찼다면 넘어가고, 그렇지 않으면 피가 얼마나 차 있는지 봐야한다. 

회복량만큼 회복했을 때, 최대피를 넘어가면 안되기 때문에 현재피가 최대피 - 회복량의 값과 같거나 작은지 확인해야한다.

그리고 연속횟수만큼 회복에 성공했다면 추가적으로 회복량이 주어지는데 여기서도 추가 회복량을 받았을 때 최대피를 넘어가는지 조건을 확인해야한다.

조건이 많아질수록 머리가 복잡해졌다. 물론 많은 시도횟수를 낭비했다.

 

function solution(bandage, health, attacks) {
  let currHealth = health;
  let currTime = 0;

  for (let [attackTime, damage] of attacks) {
    let diffTime = attackTime - currTime - 1;
    currHealth += diffTime * bandage[1] + Math.floor(diffTime / bandage[0]) * bandage[2];

    if (currHealth > health) currHealth = health;
    currHealth -= damage;
    if (currHealth <= 0) return -1;
    currTime = attackTime;
  }

  return currHealth;
}

이 코드는 구간의 차이를 활용한다.

diffTime은 다음 공격이 있을 때까지 체력 회복이 가능한 시간대이므로 diffTime 동안 체력을 회복하고 만일 체력이 최댓값을 넘어버리면 최댓값으로 맞춰준다.

 

currHealth += diffTime * bandage[1] + Math.floor(diffTime / bandage[0]) * bandage[2];

이 부분이 인상깊었다.

현재 체력의 상태를 변경하는 부분에서 diffTime만큼 체력을 회복시킬 것인데

diffTime / bandage[0] 의 수식을 이용하면 diffTime 동안 연속해서 몇 번의 회복을 했는지 알 수 있다.