Skip to main content
코딩테스트 합격자 되기 C++
15 장 동적 계획법
저자 박경록
목차
- 동적 계획법이란 ?
- 최적 부분 구조 & 중복부분문제
* 예시 : 팩토리얼 / 피보나치 수
- 동적계획법 적용하는 법
* 예시 : 계단 오르기 / 정사각형 개수 세기 / LIS
강의영상
동적 계획법이란 ?
- 복잡한 문제를 단순한 하위 문제로 나눠서 접근하는 방법
- 중복 계산을 줄이기 위해 , 이전에 구한 해를 활용함 ( 메모이제이션 )
이전의 해를 활용해야 효율적인 문제의 조건
최적 부분 구조 (Optimal Substructure)
- 문제의 최적 해결책이 하위 문제의 최적 해결책으로 부터 구성되는 경우
중복 부분 문제 (Overlapping Subproblems)
- 동일한 하위 문제가 여러번 계산 됨
예시 1 : 팩토리얼 ( 동적 계획법으로 풀어도 효율 X)
1. 크기 N 의 문제를 크기 (N-1) 문제 해로 해결
2. Fact(N-1) 은 Fact(N) 의 부분 해 ( 최적부분구조 )
3. 동일한 하위 문제가 반복되지 않음 ( 중복부분문제
X)
예시 2 : 피보나치 수 ( 동적 계획법으로 풀면 효율적 )
5
4
3
2
1
3
2
2
1
1. 크기 N 의 문제를 크기 (N-1) 문제와 (N-2)
문제의 해로 해결
2. Fibo(N-1) 은 Fibo(N) 의 부분 해 ( 최적부분구조 )
3. Fibo(5) 를 구하는 과정에서 Fibo(3) 이 2 번 나옴
즉 이전해가 반복됨 ( 중복 부분 문제 )
……
동적계획법이 뭔지는 알겠는데
문제에 어떤식으로 접근해야 하나요 ?
지금까지 배운걸 활용하면 아래순서로 하는게 제일 좋습니다 .
1. 예제 입력으로 출력 만드는 과정을 직접 손으로 작성
2. 과정을 일반화 한다 . 이 때 최종해를 구하는 과정을 , 이전해를 구하는 과정을
통해 나타낼 수 있는지 확인
3. “2.” 과정에서 이전해를 구하는 과정이 중복되는지 확인
예시 1 : 계단 오르기
N 개의 계단이 존재하고 , 한번에 1 개 혹은 2 개의 계단을 오를 수 있음
계단을 오르는 방법의 총 수는 ?
1 칸 1 칸 1
칸
2 칸 1 칸
1 칸 2 칸
1 칸 , 1 칸
2 칸
1 칸
예시 1 : 계단 오르기
1. 예제 입력으로 출력 만드는 과정을 직접 손으로 작성
예시 1 : 계단 오르기
2. 과정을 일반화 한다 . 이 때 최종해를 구하는 과정을 , 이전해를 구하는 과정을
통해 나타낼 수 있는지 확인
계단이 3 개인 경우일 때 3 번째 계단에 오르기전 상황을 가정
- 3 번째 계단이 오르려면 첫 번째 계단 혹은 두 번째 계단에 있어야 함 (1 칸
혹은 2 칸 움직일 수 있으므로 )
=> F(3) = F(2) + F(1)
숫자를 늘려보면
F(4) = F(3) + F(2)
F(5) = F(4) + F(3)
일반화 하면 F(N) = F(N-1) + F(N-2), 이때 기본 조건 , F(1) = 1, F(2) = 2
N 개 계단이 있을때 N 번째 계단에 오르기 전 상황을 가정
- N 번째 계단에 오르기 전에는 (N-1) 혹은 (N-2) 번째
계단에 있어야 함 (1 칸 혹은 2 칸 움직일 수 있으므로 )
=> F(N) = F(N-1) + F(N-2)
N 을 계속 줄여 보자
F(N-1) = F(N-2) + F(N-3)
F(N-2) = F(N-3) + F(N-4)
F(3) = F(2) + F(1) => F(2) 와 F(1) 은 직접 구해야 함
예시 1 : 계단 오르기
3. “2.” 과정에서 이전해를 구하는 과정이 중복되는지 확인
F(3) = F(2) + F(1)
F(4) = F(3) + F(2)
F(5) = F(4) + F(3)
F(N-1) = F(N-2) + F(N-3)
F(N) = F(N-1) + F(N-2)
⇒ 현재 해를 구할 때 이전 해 2 개를 사용 그리고 반복
됨 !!
1 2
1 2 3
F(1),F(2) 는 기저 조건
F(3) = F(1) + F(2)
1 2 3 5 F(4) = F(2) + F(3)
실제 구현시 해를 찾는 과정
예시 2 : 만들 수 있는 정사각형 갯수
문제 : 사각형이 주어질 때 , 만들 수 있는 정사각형의 갯수 확인
1x1 : 4
개
2x2 : 1
개
총 : 5 개
1x1 : 12 개
2x2 : 6 개
3x3 : 2 개
총 : 20 개
예시 2 : 만들 수 있는 정사각형 갯수
1. 예제 입력으로 출력 만드는 과정을 직접 손으로 작성
1x1 : 4 개 2x2 : 1 개
예시 2 : 만들 수 있는 정사각형 갯수
1. 예제 입력으로 출력 만드는 과정을 직접 손으로 작성
1x1 : 12 개 2x2 : 6 개 3x3 : 2 개
2. 과정을 일반화 한다 . 이 때 최종해를 구하는 과정을 , 이전해를 구하는 과정을
통해 나타낼 수 있는지 확인
예시 2 : 만들 수 있는 정사각형 갯수
- 1x1 사각형이 모아서 2x2 사각형을 만든다 .
- 2x2 사각형을 모아서 3x3 사각형을 만든다 .
- 2x2 사각형을 모아서 3x3 사각형을 만든다면 이는 결국 1x1 로도 만들 수 있다 .
- 현재 칸 기준 사각형의 왼쪽 / 위 / 왼쪽위대각선 에서 크기가 N 인 정사각형을 만들수
있다면 , N+1 크기의 정사각형을 만들 수 있다 .
3. “2.” 과정에서 이전해를 구하는 과정이 중복되는지 확인
예시 2 : 만들 수 있는 정사각형 갯수
1 1
1 1
1
1
1 1 1
1
1
1
1 1
1 2
1
2
1 2 2
1
2
2
1 1
1 2
1
2
1 2 3
1
2
3
1 1
1 2
2 2
2 3
2X2 가 가능하므로 1X1 도 가능
현재 칸이 NXN 정사각형을 만들수 있는지 확인하는 과정에서 ,
주변 3 칸에서 (N-1) 크기의 정사각형을 만들 수 있는지 확인함 ( 이전 문제가 중복됨 )
NxM 배열일 때 , sqrt(min(N,M)) 크기의 정사각형이 최대임
a[i][j] = min(a[i][j-1],a[i-1][j-1], a[i-1][j]) + 1, 최종답은 배열값을 모두 더하면 됨 !
부분 수열이란 ?
주어진 수열 중 일부를 뽑아 새로만든 수열 ( 이 때 순서는 유지 )
예시 3 : 최장 증가 부분 수열 (LIS)
최장 증가 부분 수열이란 ?
주어진 수열 중 일부를 뽑아 새로만든 부분 수열 중 ,
오름차순을 유지 ( 엄격한 증가 ) 하면서 가장 긴 수열
예시 3 : 최장 증가 부분 수열 (LIS)
1. 예제 입력으로 출력 만드는 과정을 직접 손으로 작성
=> ……
잠깐만요 너무 많은데요 ??, 3 칸 혹은 4 칸까지만 해봅시다
예시 3 : 최장 증가 부분 수열 (LIS)
1
4
2
3
3
2
3
LIS
2. 과정을 일반화 한다 . 이 때 최종해를 구하는 과정을 , 이전해를 구하는 과정을 통해 나타낼 수 있는지
확인
예시 3 : 최장 증가 부분 수열 (LIS)
1 4 2 3 1 5 7 3
1
1 4
1 4 2
1 4 2 3
1 4 2 3 1
1 4 2 3 1 5
1 4 2 3 1 5 7
1 4 2 3 1 5 7 3
한번에 전체 해를 구하는건 어렵다 .
각 배열의 원소를 끝으로하는 LIS 를 구해보자
K 번째 위치의 LIS 를 LIS(K) 라고 한다면 ,
LIS(K) = max(LIS(1……(X), X 번째 원소는 K 번째 원소보다 작음 , 1 <= X < K ) + 1
=> X 번째 원소는 K 번째 원소보다 작아야 하는 이유는 맨 뒤에 K 번째 원소가 와야
하므로
정리
아래 두 조건을 만족하는 경우 동적계획법으로 접근하면 효율적
- 중복부분구조
=> 현재 해를 구하기 위해 이전 해가 중복적으로 사용되는지 확인
- 최적부분문제
=> 현재 해가 이전해를 활용해서 해결할수 있는지 확인
현재 해가 이전해를 활용해서 해결할 수 있지만 ,
이전해가 중복되지 않는 경우는 동적계획법으로 풀어도 효과가 없다 .
- 팩토리얼 ( 최적부분 문제 O, 중복부분구조 X)
- 피보나치 ( 최적부분 문제 O, 중복부분구조 O)
커뮤니티 소개 ( 오픈카톡방 ) cont’d
- 저자 직접 운영
- 대략 400 명 정도 인원이 자유롭게 소통
- 개인적인 주제 및 코딩 관련 소통 가능
커뮤니티 소개 ( 오픈카톡방 )
커뮤니티 소개 ( 깃허브 ) cont’d
- 책 문제의 정답코드
- 코딩테스트 준비를 위해 필요한 자료구조 및 알고리즘
- C++ 기본 문법
- STL 의 성능 비교
커뮤니티 소개 ( 깃허브 )
커뮤니티 소개 ( 디스코드 ) cont’d
- 모각코 진행
- 공식 스터디 / 개인 스터디 모집 공고 및 진행
- 책 관련 문의 / 답변
커뮤니티 소개 ( 디스코드 )