금화 모으기
start에서 exit까지 이동하려 한다. 오른쪽이나 위쪽 방향으로만 이동할 수 있을 때, 모을 수 있는 금화의 최대 개수를 구하는 문제
다 따져볼 수도 있지만 그러면 오래 걸린다.
부분 문제
(i, j)번째 칸에 도착하려면 (i-1, j)나 (i, j-1)에서 오기 때문이다. 최단거리로 이동한다 가정했으므로 (i-1, j)나 (i, j-1)에서 오는 경우가 겹치지 않는다. 그래서 따로 구한 후 max로 더 큰 값을 택하면 된다.
동전 거스름돈
- N원의 거스름돈을 돌려줄 때, 동전의 개수가 최소가 되도록 거스름돈을 돌려주는 방법을 구하는 문제
- 동전의 종류에는 1원, 4원, 6원이 있음
예를 들어 8원을 거슬러 준다고 하자.
먼저 greedy하게 접근해, 가장 큰 단위의 동전을 먼저 사용한다고 해보자. 그럼 6원, 1원, 1원으로 거슬러 주므로 동전의 개수는 3이다.
그러나 실제로는 4원짜리 동전 두 개로도 거스름돈을 줄 수 있으므로 , 그리디 방법으로는 정답을 구하기 어렵다는 것을 알 수 있다. 그럼 이제 DP로 해결해보자.
Recursion (Top-down)
세 가지 동전 각각을 택해 재귀적으로 해결할 수 있다.
1원짜리 동전 한 개 + 7원에 대한 최적해
4원짜리 동전 한 개 + 4원에 대한 최적해
6원짜리 동전 한 개 + 2원에 대한 최적해
7원에 대한 최적해는 다시 1, 4, 6원짜리 동전을 선택하고 나머지 액수에 대한 최적해를 구함
풀 수 있지만 중복 계산을 너무 많이 하게 된다. Avoid re-computing solutions for these subproblems!
DP Approach (Bottom-up)
- 1원에 대한 최적해 → (선택) 2원에 대한 최적해 → (선택) 3원에 대한 최적해 → (선택) 4원에 대한 최적해 → (선택) …
- C[j]: j원을 거슬러 줄 때의 최적해
n | sol | choice |
---|---|---|
8 | 1 | C[n-1] + 1 = 3, C[n-4] + 1 = 2, C[n-6] + 1 = 3 → 3 |
7 | 2 | C[n-1] + 1 = 2, C[n-4] + 1 = 4, C[n-6] + 1 = 2 → 2 |
6 | 1 | C[n-1] + 1 = 3, C[n-4] + 1 = 2, C[n-6] + 1 = 2 → 2 |
5 | 2 | C[n-1] + 1 = 2, C[n-4] + 1 = 2 → 2 |
4 | 1 | C[n-1] + 1 = 4, C[n-4] + 1 = 1 → 1 |
3 | 3 | C[n-1] + 1 = 3 → 3 |
2 | 2 | C[n-1] + 1 = 2 → 2 |
1 | 1 | C[n-1] + 1 = 1 → 1 |
0 | 0 | 0 |
프리랜서의 일정 정하기
전에 백준에서 끙끙대면서 푼 회의 문제
프리랜서에게 10일간의 작업에 대한 요청이 있고, 하나의 작업을 하는 동안 다른 작업은 할 수 없다고 할 때, 주어진 일정에서 수당의 합이 가장 크도록 작업을 선택하는 문제
Greedy하게 푼다면 수당이 제일 많은 T3을 선택해야 하지만 , T3이 다른 모든 일정과 겹치기 때문에 다른 일정을 선택할 수가 없다. 하지만 T1+T7을 선택하면 더 많은 수당을 받을 수 있다.
Job들을 끝나는 순서대로 보자. 끝나는 시각마다 그때까지의 최대 금액을 계산하는 것이다.
위의 예시에서는 t=3일 때의 최대 금액은 15, t=4는 20, t=5일 때는 30이다.
t=6일 때는 T9가 끝나므로 여러 가지 케이스가 생기는데, 어떻게 하면 좋을까?
- 신청 작업이 1개일 경우 무조건 선택
- 신청 작업이 2개일 경우
- 겹친다면 더 많은 돈을 지불하는 직업을,
- 겹치지 않는다면 두 작업을 모두 선택
부분 문제
각 작업이 마치는 시간을 key로 하여 전체 작업을 다시 정렬하고 순서대로 번호를 붙임. 즉, 전체 작업 중 j번째로 미치는 작업임
OPT(j): 1부터 j까지의 작업에 대한 최적의 해
- OPT가 작업 j를 선택하지 않는 경우: OPT(j) = OPT(j-1)
- OPT가 작업 j를 선택함: OPT(j) = w(j) + OPT(p(j))
- p(j)는 작업 j와 겹치지 않고 p(j) < j인 작업들 가운데 맨 마지막 작업
- W(j는 작업 j를 수행했을 때 받은 돈 액수
- OPT(j) = max { OPT(j-1), w(j) + OPT(p(j)) }
집합에서 k개 선택하기
N개의 원소로 구성된 집합 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}에서 서로 다른 k개를 순서 없이 선택하는 방법의 수를 구하는 문제
DP
- 만약 답이 존재한다면 그 답은 경우들로 나눠지는지 생각해보자,
- 크기 4의 부분집합 {a, b, c, d}이 있다면 그것은 두 가지로 나눠볼 수 있다.
- a를 포함하는 것
- a를 포함하지 않는 것
n’(<n)에서 서로 다른 k’(k<n)개를 선택하는 부분 집합들의 개수를 구하는 문제들에 대해 답을 알고 있다고 하자. 그러면 n개에서 선택한 크기 k개의 부분 집합은 두 가지 경우에 속한다.
- case 1: a를 포함하는 부분집합들
- a를 제외한 n-1개에서 k-1개를 선택한 부분집합들에 a를 추가
- case 2: a를 포함하지 않는 부분집합들
- a를 제외한 n-1개에서 k개를 선택한 부분 집합들
전체 답은 case 1 + case 2 –> C(n, k) = C(n-1, k-1) + C(n, n-k)
이항계수 구하는 공식: nCk = n! / (k! (n-k)!)
그러나 n!이나 k!은 계산량이 많기 때문에 실제로 C(n, k) = C(n-1, k-1) + C(n, n-k)은 다음과 같이 계산한다.
C(n, k) =
C(n-1, k-1) + C(n-1, k) (0 < k < n)
or
1 (if k == 0 or k == n)
완전 정보 게임 (NIM Game)
- 완전 정보 게임
- 게임의 정보가 참가자 모두에게 공개된 게임
- 숨어있는 정보가 없음
- 누가 먼저 하느냐에 따라 승부가 이미 결정되어 있음
- 바둑, 오목, 체스 등
- 불완전 정보 게임
- 정보가 확률적으로 주어짐
- 모든 정보가 공개되어 있지는 않음
- 화투, 포커, 스포츠 베팅 등
바둑돌 가져가기 (1)
바둑돌이 K개 있다. 두 사람이 번갈아가면 자신의 차례에 1개, 2개의 돌을 가져갈 수 있다. 자신의 차례에 동작을 할 ㅜ없으면 그 사람이 진다. 이기는 방법이 있는 사람과 그 사람이 이기는 방법을 구하시오.
부분 문제
D(i): 돌의 개수가 i개일 때 상대방이 어떤 수를 써도 이기는 방법이 있는 경우 W(win)으로, 그렇지 않은 경우는 L(lose)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
L | W | W | L |
0을 받으면 이길 방법이 없으므로 lose이다. 돌의 개수가 1인 경우, 내가 그 돌을 가져가 버리면 상대방은 돌의 개수가 0이므로 진다. 따라서 돌이 하나인 경우는 W이다. 2에서 하나를 가져가면 상대방이 이길 수도 있지만, 둘 다 가져가면 상대방이 절대 이길 수 없기 떄문에 내가 이긴다.
i==3일 때는, 내가 하나를 가져가도 상대방이 W이고 내가 두 개를 가져가도 상대방이 W이므로 나는 L이다.
즉, i-1, i-2가 모두 W이면 자신은 L이다.
이런 식으로 9회까지 진행한 결과는 아래와 같다. | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |–|–|–|–|–|–|–|–|–|–| | L | W | W | L | W | W | L | W | W | L |
–> 3의 배수에서만 L임을 알 수 있다.
바둑돌 가져가기 (2)
바둑돌이 K개 있다. 두 사람이 번갈아가며 자신의 차례에 1개, 3개, 4개의 돌을 가져갈 수 있다. 자신의 차례에 동작을 할 수 없으면 그 사람이 진다. 이기는 방법이 있는 사람과 그 사람이 이기는 방법을 구하시오.
부분문제
D(i): 돌의 개수가 i개일 때 상대방이 어떤 수를 써도 이기는 방법이 있는 경우 W(win)으로, 그렇지 않은 경우는 L(lose)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
L | W | L | W | W | W | W | L | W | L | W | W | W | W | L |
바둑돌 가져가기 (3)
바둑돌이 K개 있다. 두 사람이 번갈아가며 자신의 차례에 1개, 3개, 4개의 돌을 가져갈 수 있다. 단, 앞사람이 가져간 개수의 돌은 가져갈 수 없다(따라하기 금지). 자신의 차례에 동작을 할 수 없으면 그 사람이 진다. 이기는 방법이 있는 사람과 그 사람이 이기는 방법을 구하시오.
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
-1 | L | L | L | W | L | W | L |
-3 | L | W | W | W | L | W | L |
-5 | L | W | W | W | L | W | L |
-1: 직전에 한 칸 내려온 경우. 따라하기 금지니까 -3일 때 세 칸 이동한 값이랑 -5에서 다섯 칸 이동한 값 중 L이 하나라도 있으면 W, 모두 W인 경우 L이다.
바둑돌 가져가기 (4)
바둑돌이 K개 있다. 두 사람이 번갈아가며 자신의 차례에 (1, 1), (3, 2), (2, 0)개의 (흰돌, 검은돌)을 가져갈 수 있다. 자신의 차례에 동작을 할 수 없으면 그 사람이 진다. 이기는 방법이 있는 사람과 그 사람이 이기는 방법을 구하시오.
W/B | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
0 | L | L | L | L | L | L | L |
1 | L | W | W | W | W | W | W |
2 | W | W | W | W | W | W | W |
3 | W | L | W | W | W | W | W |
4 | L | L | W | L | L | L | L |
5 | L | W | W | L | W | W | W |
6 | W | W | L | W | W | W | W |