백준 14501번: 퇴사 - javascript
백준 14501번: 퇴사
문제 설명
접기/펼치기
상담원으로 일하고 있는 백준이는 퇴사를 하려고 한다.
오늘부터 N+1일째 되는 날 퇴사를 하기 위해서, 남은 N일 동안 최대한 많은 상담을 하려고 한다.
백준이는 비서에게 최대한 많은 상담을 잡으라고 부탁을 했고, 비서는 하루에 하나씩 서로 다른 사람의 상담을 잡아놓았다.
각각의 상담은 상담을 완료하는데 걸리는 기간 Ti와 상담을 했을 때 받을 수 있는 금액 Pi로 이루어져 있다.
N = 7인 경우에 다음과 같은 상담 일정표를 보자.
- | 1일 | 2일 | 3일 | 4일 | 5일 | 6일 | 7일 |
---|---|---|---|---|---|---|---|
Ti | 3 | 5 | 1 | 1 | 2 | 4 | 2 |
Pi | 10 | 20 | 10 | 20 | 15 | 40 | 200 |
1일에 잡혀있는 상담은 총 3일이 걸리며, 상담했을 때 받을 수 있는 금액은 10이다. 5일에 잡혀있는 상담은 총 2일이 걸리며, 받을 수 있는 금액은 15이다.
상담을 하는데 필요한 기간은 1일보다 클 수 있기 때문에, 모든 상담을 할 수는 없다. 예를 들어서 1일에 상담을 하게 되면, 2일, 3일에 있는 상담은 할 수 없게 된다. 2일에 있는 상담을 하게 되면, 3, 4, 5, 6일에 잡혀있는 상담은 할 수 없다.
또한, N+1일째에는 회사에 없기 때문에, 6, 7일에 있는 상담을 할 수 없다.
퇴사 전에 할 수 있는 상담의 최대 이익은 1일, 4일, 5일에 있는 상담을 하는 것이며, 이때의 이익은 10+20+15=45이다.
상담을 적절히 했을 때, 백준이가 얻을 수 있는 최대 수익을 구하는 프로그램을 작성하시오.
입력
접기/펼치기
첫째 줄에 N (1 ≤ N ≤ 15)이 주어진다.
둘째 줄부터 N개의 줄에 Ti와 Pi가 공백으로 구분되어서 주어지며, 1일부터 N일까지 순서대로 주어진다. (1 ≤ Ti ≤ 5, 1 ≤ Pi ≤ 1,000)
출력
접기/펼치기
첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다.
예시
접기/펼치기
입력
10
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
출력
55
접근
brute force한 재귀 문제다.
그냥 재귀만 돌리면서 현재 날짜의 상담과 다음날짜를 고를경우의 max를 비교하는게 아니라 1일부터 퇴사일 N일까지 모든 경우를 비교해보면서 최대 이득을 뽑아야하기 때문이다.
재귀 자체의 설계는 간단하다.
- 시작일(0)부터 N일 전까지 반복문을 돌린다.
- 현재 i항의 상담 비용이 퇴사일보다 낮으면 현재 상담비용을 더한 값을 시작일로, 상담 이익을 더해준 값을 합계로 바꿔서 다시 재귀로 넣어준다.
-
만약 현재 i항의 상담비용이 퇴사일보다 높으면 지금까지 보관한 합계를 전역변수 max과 비교해서 더 큰 값을 max에 넣어준다.
- 그리고 반복문이 종료되면 max의 비교를 한 번 더 해준다.
4번의 이유는 위에서 문제설명과 다른 예시값을 예시에 넣은 이유이기도한데, 문제 설명에서는 마지막즈음의 6일과 7일의 상담기간이 각각 4일과 2일으로 퇴사일을 훌쩍 넘어버려서 위의 과정 중 3번에서 최대값이 나오게된다.
하지만 만약 최종일까지 상담비용이 1일씩 이라면?
그런 예시가 바로 위에 예시에 넣은 입/출력값인데 매일매일 1일짜리 상담에 이익은 1부터 10까지라면 당연히 최대값은 55다.
하지만 만약 재귀코드에서 반복문 내에서만 최대값을 출력한다면 마지막날에 +1한 상담이 잡히지 않는다.
그래서 나는 반복문이 끝나고 최종적으로 한 번 더 잊어버린 합계가 없는지 넣어주기 위해 반복문 뒤에 max비교값을 한 번 더 넣게 됬다.
다른방법도 있을텐데 그냥 함수 재귀 콜을 한 번 더 하는 방식으로 했다
정답 코드
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
let max = 0;
rl.on('line', function (line) {
input.push(line);
})
.on('close', async function () {
// 답안 작성
let n = input.splice(0,1);
let schedule = [];
input.reduce((acc,cur)=>{
let tmp = cur.split(' ');
schedule.push({date:tmp[0]*1,price:tmp[1]*1});
},'')
re_schedule(schedule, 0, n, 0);
console.log(max)
process.exit();
});
let re_schedule = function(schedule, start, n, sum){
for(let i = start; i<n; i++){
if((i+schedule[i].date)<=n)re_schedule(schedule, i+schedule[i].date, n, sum+schedule[i].price);
else max = Math.max(max, sum);
}
max = Math.max(max, sum);
return ;
}
댓글남기기