2. Dynamic Programming
• Wikipedia
: method for solving complex problems by breaking them down into simpler subproblems
1. 부분 문제의 정의(Defining subproblems)
2. 부분 문제 간의 점화 관계 유추(Finding recurrences)
3. 초기 상태 및 특수 경우 명세(Solving the base cases)
3. Simple Problems
• 부분합 : S(n) = A(n) + S(n-1)
• 피보나치 수열 : F(n) = F(n-1) + F(n-2)
• n 종류의 X_i원의 동전들이 무한히 많을 때, K원을 만들기.
: For (D(0) = 1, a = 1 to n) { //a : 어느 종류의 동전
for (b = X_a to K) D(b) += D(b – X_a); //b원을 만들기 위해
}
4. BOJ 1405 (미친 로봇)
• 4방향(동서남북), N번 움직임.
• 로봇이 같은 곳을 다시 방문하지 않을 때, 로봇의 이동 경로가 ‘단순’하다. (로봇이 시작하
는 위치가 처음 방문한 곳이다.)
• 로봇의 이동 경로가 단순할 확률을 구하기.
• 예를 들어, EENE와 ENW는 단순하지만, ENWS와 WWWWSNE는 단순하지 않다. (E는 동,
W는 서, N은 북, S는 남)
5. BOJ 1405 (미친 로봇)
• 부분 문제의 정의.
• N번 움직였다면, (N-1)번까지 움직였을 때의 정보를 이용하면…
• 로봇의 이동경로가 단순하다는 조건을 매번 지켜주면 마지막 위치만이 중요!
• (N-1)번까지 움직였을 때의 최종 위치…
• D(X, Y, K)를 로봇이 K번 더 움직일 수 있고, 현재 위치가 (X, Y)라고 정의.
• D(X, Y, K) = Sum( D(X2, Y2, K-1) * possibility(direction) )
• N 제한이 14이하.
• 경우의 수가 적어서 recursion 관계만 찾아도 충분!...
6. BOJ 1750 (서로소의 개수)
input : 수열의 크기가 N인 수열.
한 개 이상의 수를 선택했을 때에, 선택한 수들의 GCD가 1이 되는 것의 개수.
1 ≤ N ≤ 100, 1 ≤ Si ≤ 100,000
7. BOJ 1750 (서로소의 개수)
1. GCD 연산은 순서에 상관없이 결과가 같다. Ex) GCD(4, 6, 12) = GCD(12, 6, 4)
2. 수열의 K번째 수까지에 대한 답을 구했다면, K+1번째에서는 이전에 계산한 정보를 활용할 수 없을까.
3. 어떤 수들을 골랐을 때에 그 집합을 독립적으로 생각할 수 있는 기준 : 최대공약수
4. D(index, gcd_number)
: 수열의 index번째 수까지 고려했을 때에, 1개 이상의 수를 골라서 그 수들의 최대공약수가 gcd_number일 경우의 수
8. BOJ 1750 (서로소의 개수)
D(index-1, 0) ~ D(index-1, max(S_i))까지 계산했다고 가정.
S_index = X라 하자.
1) gcd_number != X
D(index, GCD(gcd_number, X)) += D(index-1, gcd_number)
D(index, gcd_number) += D(index-1, gcd_number)
2) gcd_number == X
D(index, X) += D(index-1, X)*2(X를 기존의 집합에 추가하고/안하고) + 1(X 혼자)
9. BOJ 11053 (가장 긴 증가하는 부분 수열)
• Longest Increasing Subsequence
• D(i) : i번째 수에서 끝이 날 때에, 가장 긴 부분 수열의 길이
• D(i) = max( D(j) + 1 ) … if)A(j) < A(i)
10. Bitmask DP
• Status : 2진수로 표현.
• 1<<k : k번째 사건에 해당하는 비트.
• X & Y : X와 Y의 공통된 상태.
• X ^ Y : X와 Y의 서로 다른 상태.
• X | Y : X에서 벌어진 사건들과 Y에서 벌어진 사건들의 합.
• Define Tables like D(Status, … )…
12. BOJ 1693 (트리 색칠하기)
• n개의 정점으로 이루어진 트리가 있다. 이 트리의 각 정점을 색칠하려고 한다.
• 색칠을 할 때에는 1, 2, 3, …, n번 색깔 중에 하나로 색칠하여야 한다. 각 색깔을 사용하여
한 개의 정점을 색칠할 때마다 1, 2, …, n의 비용이 든다. 즉, i번 색깔로 한 개의 정점을 색
칠하면 i만큼의 비용이 든다는 것이다. 또한 정점에 색칠을 할 때에, 주어진 트리 상에서
인접해 있는 서로 다른 두 정점은 서로 다른 색깔로 칠해져야 한다.
• 이를 만족하면서, 전체 정점들을 색칠하는데 드는 총 비용을 최소화 하려 한다. 최소 비용
을 계산하는 프로그램을 작성하시오.
15. BOJ 1693 (트리 색칠하기)
• D(a, Status) : 노드 a에 Status라는 색을 칠할 때에 필요한 최소 비용.
16. 결론
• Wikipedia
: method for solving complex problems by breaking them down into simpler subproblems
1. 부분 문제의 정의(Defining subproblems)
2. 부분 문제 간의 점화 관계 유추(Finding recurrences)
3. 초기 상태 및 특수 경우 명세(Solving the base cases)