일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 머신러닝
- SWEA
- 전산기초
- Object detection
- 실전알고리즘
- cs
- 백준
- C++
- ubuntu
- 3단계
- AWS
- 이것이 코딩테스트다 with 파이썬
- pytorch
- 그리디
- 프로그래머스
- ssd
- 2단계
- Python
- 자료구조 및 실습
- docker
- 구현
- MySQL
- 파이썬
- 딥러닝
- 모두를 위한 딥러닝 강좌 시즌1
- test-helper
- STL
- 코드수행
- 1단계
- CS231n
- Today
- Total
곰퓨타의 SW 이야기
[백준 14501번 퇴사] dynamic algorithm으로 뿌시기! 본문
이 문제를 보자마자 알고리즘 시간에 다루었던 0-1 knapsack problem이 떠올랐다.
수업시간에 이 문제를 greedy 한 방법과 dynamic 한 방법으로 사용하여 풀었었다.
greedy한 방법은 항상 최적의 해를 구해다 주지는 않는다는 기억이 있었기 때문에,
dynamic한 방법으로 접근하고자 하였다.
사실 접근방법을 알았지만, 적용 속도가 좀 느리기 때문에 어제부터 친구들과 풀었는데 오늘 풀렸다.
해결해야 하는 문제는 다음과 같았다.
14501번: 퇴사
첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다.
www.acmicpc.net
문제설명↓
문제
상담원으로 일하고 있는 백준이는 퇴사를 하려고 한다.
오늘부터 N+1일째 되는 날 퇴사를 하기 위해서, 남은 N일 동안 최대한 많은 상담을 하려고 한다.
백준이는 비서에게 최대한 많은 상담을 잡으라고 부탁을 했고, 비서는 하루에 하나씩 서로 다른 사람의 상담을 잡아놓았다.
각각의 상담은 상담을 완료하는데 걸리는 기간 Ti와 상담을 했을 때 받을 수 있는 금액 Pi로 이루어져 있다.
N = 7인 경우에 다음과 같은 상담 일정표를 보자.
1일2일3일4일5일6일7일TiPi3 | 5 | 1 | 1 | 2 | 4 | 2 |
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)
출력
첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다.
예제 입력 1
7
3 10
5 20
1 10
1 20
2 15
4 40
2 200
예제 출력 1
45
1. 입력 받기
파이썬으로 입력 받을 때 input()을 주로 사용했지만, stdin과도 친해지기 위해 저번에 익힌 stdin을 사용하여 입력 받았다.
from sys import stdin
n = int(stdin.readline())
consult = []
for i in range(n):
t,p =map(int, stdin.readline().split())
consult.append([t,p])
2. dp 활용하기
dp는 0부터 n까지의 인덱스를 갖는 배열이다.
이 배열은 각 날 수에 최대로 돈을 벌 수 있는 경우의 값을 저장하기 위해 만들었다.
i+consult[i-1][0]-1은 현재 날 수인 i에서 consult[i-1][0] 일 만큼 상담할 것이고, 첫째날을 포함하기 때문에 -1 해주었다.
i+consult[i-1][0]-1는 dp의 index에 들어갈 것이므로 n보다 커지면 out of range 가 된다.
따라서 i+consult[i-1][0]-1가 n+1 보다 작은 경우에는 아래의 책과 같이 업데이트 해주었다.
(이는 알고리즘 시간에 강의노트에서 발췌했던 책의 일부분이다.)
이 책과 같이 i+consult[i-1][0]-1 index에 해당하는 값은,
1. 현재 이부분의 값과 2. 전날까지의 최대 pay인 dp[i-1]에 현재 날짜인 i 의 pay 값을 나타내는 consult[i-1][1] 값을 더한 것의
최댓값으로 업데이트 하였다.
마지막으로, 해당 날짜에 해당하는 dp 배열 값은 해당 날짜까지의 최댓값으로 업데이트 해주었다.
(이전까지의 값이 현재 날짜가 갖는 값보다 크다면 그 값으로 저장해주기 위함. )
그리고 마지막 n index에 있는 수가 dp 배열에서 가장 큰 수를 가지고 있으므로, 이는 최대로 벌 수 있는 pay 값이다.
따라서 이 값을 출력해주면 문제는 통과된다!
dp = [0 for i in range(n+1)]
for i in range(1,n+1):
if i+consult[i-1][0]-1 < n+1:
dp[i+consult[i-1][0]-1] = max(dp[i+consult[i-1][0]-1],consult[i-1][1]+dp[i-1])
dp[i] = max(dp[:i+1])
print(dp[-1])
3. 최종 코드
from sys import stdin
n = int(stdin.readline())
consult = []
for i in range(n):
t,p =map(int, stdin.readline().split())
consult.append([t,p])
dp = [0 for i in range(n+1)]
for i in range(1,n+1):
if i+consult[i-1][0]-1 < n+1:
dp[i+consult[i-1][0]-1] = max(dp[i+consult[i-1][0]-1],consult[i-1][1]+dp[i-1])
dp[i] = max(dp[:i+1])
print(dp[-1])
삼성 기출 문제는 그동안 배운 알고리즘 지식 없이는 풀 수 없는 것 같다.😂
문제를 풀면서 프로그래밍 지식을 쌓아야 겠다 ㅜ_ㅜ
'TIL > 백준' 카테고리의 다른 글
[백준 1759 암호 만들기] 조건 주의하기 (0) | 2021.04.15 |
---|---|
[백준 1929 소수 구하기] set 함수 주의 (0) | 2021.04.15 |
[백준 14889 스타트와 링크] 문제를 이해하기! (0) | 2021.01.30 |
[백준 14888번 연산자 끼워넣기] itertools 의 활용! (0) | 2021.01.24 |
[백준 13460번 구슬 탈출 2] bfs 활용하여 뿌시기 (0) | 2021.01.22 |