728x90
문제 자체는 dp를 활용해서 해결할만한 문제였다.
우선 다트는 1~20까지 점수가 있는 판이란 점을 생각하자.
dp를 만드는데 [Infinity,0]으로 각 칸을
dp[n] 이라면 dp[n][0]은 n이라는 점수를 만들기 위해 필요한 다트의 횟수, dp[n][1]은 싱글이나 불을 던진 횟수를 저장하면 될 것이라고 생각했다.
이런방식으로 dp를 구성하면 n이라는 점수를 만들기 위해서 이전 dp에서 2개만 합하면 된다!
또한 n이 점수이므로 dp[n]을 만들기 위해 dp[i]를 사용했다면 자연스럽게 더해줄 점수는 dp[n-i]가 된다.
이렇게 dp들을 검사하며
1. 다트를 던지는 횟수가 적은경우
2. 다트를 던지는 횟수가 같다면 싱글이나 불 다트를 던진 횟수가 많은경우
위 두 조건중 하나에 충족하면 dp를 업데이트해주면된다.
그런데,, 시간초과가 발생했다 ㅠㅠ
해당 부분을 고민하다가 힌트를 약간 얻었다. 일정점수 이상(250점) 이상부터는 무조건 60점을 우선 맞춰놓고 그 이하에서 계산하는게 우선이라는 점이다. 따라서 넉넉하게 310개의 dp공간을 두고, 250점 이상이라면 우선 60점을 맞춰놓고 생각하게 하면 dp의 크기를 300여개로 제한한 상태에서 문제를 해결할 수 있다.
function solution(target) {
let ret = 0
if (target > 310){
target -= 250
ret += ~~(target/60)
target %=60
target += 250
}
const dp = [...Array(311)].map(v => [Infinity,0])
for (let i = 1 ; i <= 20; i++){
dp[i*2] = [1,0]
dp[i*3] = [1,0]
}
for (let i = 1 ; i <= 20; i++){
dp[i] = [1,1]
}
dp[50] = [1,1]
for (let i = 21 ; i < dp.length ; i++){
for (let j = 1 ; j < i ; j++){
const cnt = dp[j][0]+dp[i-j][0]
const sbCnt = dp[j][1]+dp[i-j][1]
if (dp[i][0]>cnt){
dp[i] = [cnt,sbCnt]
} else if (dp[i][0]===cnt && dp[i][1]<sbCnt){
dp[i] = [cnt,sbCnt]
}
}
}
dp[target][0] += ret
return dp[target]
}
728x90
'FrontEnd > 프로그래머스' 카테고리의 다른 글
[JS] 코딩테스트 공부 (2) | 2023.10.30 |
---|---|
[JS] 등산코스 정하기 (2) | 2023.10.28 |
[JS] 고고학 최고의 발견 (0) | 2023.10.23 |
[JS] 2차원 동전 뒤집기 (0) | 2023.10.23 |
[JS] 부대복귀 (1) | 2023.10.21 |