DP Algorithm
"๋์ ๊ณํ๋ฒ(Dynamic Programming)์ด๋ ํฐ ๋ฌธ์ ๋ฅผ ์์ ๋ฌธ์ ๋ก ๋๋์ด ํธ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค."
ํ๋์ ๋ฌธ์ ๋ฅผ ์ฌ๋ฌ๊ฐ์ ์์ ๋ฌธ์ ๋ก ๋๋์ด ๊ทธ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅ(๋ฉ๋ชจ์ด์ ์ด์ )ํ์ฌ ๋ค์ ํฐ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๋ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. Dynamic Programming ์ด๋ผ๋์ด๋ฆ์ด ๋ญ๊ฐ ๋์ ์ผ๋ก ํ๋ก๊ทธ๋๋ฐ์ ํด์ผํ๋? ์๊ฐํ ์์๋๋ฐ ์ ํ์๋๋ค. ๊ทธ๋ฅ ํฐ๋ฌธ์ ๋ฅผ ์์๋ฌธ์ ๋ก ์ชผ๊ฐ์ ๊ทธ๋ต์ ์ ์ฅํด๋๊ณ ํ์ฉํ๋ค๋๊ฒ์ ์ง์คํ๋ฉด๋ ๊ฒ์ด๋ค. (๊ธฐ์ตํ๋ฉฐํ๊ธฐ ์๊ณ ๋ฆฌ์ฆ)
์ด๋ฌํ DP๋ ๋ถํ ์ ๋ณต ์๊ณ ๋ฆฌ์ฆ๊ณผ๋ ๋ฎ์ ๋ถ๋ถ์ด ์๋ค. ํ์ง๋ง ๋ถํ ์ ๋ณต์์๋ ๋ถ๋ถ๋ฌธ์ ์ ๊ณ์ฐ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋ ๋ฉ๋ชจ์ด์ ์ด์ ์ ํ์ฉํ์ง ์๋๋ค. ์ด๊ฒ์ด DP์ ๋ถํ ์ ๋ณต์ ์ฐจ์ด์ด๊ณ , ๊ณ์ฐ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํด๋๊ณ ํ์ฉํ๊ธฐ ๋๋ฌธ์ ์๊ฐ๋ณต์ก๋ ๋ฉด์์ DP๊ฐ ์ ๋ฆฌํ๋ค.
DP ์ฌ์ฉ์ด์
DP๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ญ๊น? ์ฌ๊ท(Recursion)์ด DP์ ๋งค์ฐ ์ ์ฌํ๊ฒ ๋์ํ๋ค. ํ์ง๋ง ๋์ ์ฐจ์ด์ ์ด ์๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ฌ๊ท๋ฅผ ๋จ์ํ๊ฒ ์ฌ์ฉํ๋ฉด ๋์ผํ ์์ ๋ฌธ์ ๋ค์ด ์ฌ๋ฌ๋ฒ ๋ฐ๋ณต๋์ด ๋นํจ์จ์ ์ธ ๊ณ์ฐ์ด ๋ ์๋ ์๋ค๋ ์ ์ด๋ค.
์๋ฅผ๋ค์ด ํผ๋ณด๋์น ์์ด์ ์ดํด๋ณด๋ฉด
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ...
ํผ๋ณด๋์น์๋ฅผ ๊ตฌํ๊ณ ์ถ์๋ ์ฌ๊ท๋ก ํจ์๋ฅผ ๊ตฌ์ฑํ๋ฉด
return f(n) = f(n-1) + f(n-2) (n > 2)
์ด๋, f(n-1), f(n-2)์์ ํจ์๋ฅผ 1๋ฒ์ฉ ํธ์ถํ๋ฉด, ๋์ผํ ๊ฐ์ 2๋ฒ์ฉ ๊ตฌํ๊ฒ ๋๋ค. ์๋ฅผ๋ค์ด 100๋ฒ์งธ ํผ๋ณด๋์น์๋ฅผ ๊ตฌํ๊ฒ ๋๋ค๋ฉด... ๊ธฐํ๊ธ์์ ์ธ ํจ์์ ํธ์ถ์ด ์ผ์ด๋๋ค.
์ ๊ทธ๋ผ ์ฌ๊ธฐ์ DP์ ํจ์จ์ฑ์ ๋ณผ์์๋ค. ์์ ๊ทธ๋ฆผ์ ๋ณด๋ฉด ์์ ๋ฌธ์ ์ ๊ฒฐ๊ณผ๊ฐ ์ค๋ณต๋๋๊ฒ์ ๋ณผ์์๊ณ , ์ด๋ฅผ ์ ์ฅํด๋๊ณ ์ฌ์ฌ์ฉํ๋ค๋ฉด ์์์ ๊ณ์ฐํ ๊ฐ์ ๋ฐ๋ณตํ ํ์๊ฐ ์์ด, ํจ์ฌ ์ ์ ํจ์ ํธ์ถ๋ก ๊ณ์ฐ์ด ๊ฐ๋ฅํด์ง๋ค.
๋งค์ฐ ํจ์จ์ ์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์์๋๋ฐ, ์๊ฐ๋ณต์ก๋๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ณด๋ฉด
O(n^2) > O(f(n)) ์ผ๋ก ๊ฐ์ (๋คํญ์ ์์ค, ๋ฌธ์ ์ ๋ฐ๋ผ ๋ค๋ฅด๋ค.) ๊ฐ๋ฅํ๋ค.
DP์ ์ฌ์ฉ์กฐ๊ฑด
- Overlapping Subproblems(๊ฒน์น๋ ๋ถ๋ถ๋ฌธ์ )
- Optimal Substructure(์ต์ ๋ถ๋ถ๊ตฌ์กฐ)
1. Overlapping Subproblems(๊ฒน์น๋ ๋ถ๋ถ๋ฌธ์ )
DP๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฌธ์ ๋ฅผ ๋๋๊ณ ๊ทธ ๋ฌธ์ ์ ๊ฒฐ๊ณผ๊ฐ์ ์ฌํ์ฉํด์ ๋ต์ ๊ตฌํ๋ค. ๊ทธ๋์ ๋์ผํ ์์ ๋ฌธ์ ๋ค์ด ๋ฐ๋ณตํ์ฌ ๋ํ๋๋ ๊ฒฝ์ฐ์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
๋ค์๋งํด์ DP๋ ๋ถ๋ถ ๋ฌธ์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ์ฌ ์ฌ ๊ณ์ฐํ์ง ์์์ผ ํ๋๋ฐ, ๋ถ๋ถ๋ฌธ์ ๊ฐ ๋ฐ๋ณต์ ์ผ๋ก ๋ํ๋์ง์์ผ๋ฉด ์ฌ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ์ฌ ๋ถ๋ถ๋ฌธ์ ๊ฐ ์ค๋ณต๋์ง ์๋๊ฒฝ์ฐ์๋ ์ฌ์ฉํ ์๊ฐ ์๋ค.
์๋ฅผ๋ค์ด ์ด์งํ์๊ณผ ํผ๋ณด๋์น์์ด์ ๋น๊ตํด๋ณด์.
์ด์งํ์์ ๊ฒฝ์ฐ๋ ํน์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฌ๋ ๋ฐฐ์ด์์์ ์์น๋ฅผ ์ฐพ๊ธฐ๋๋ฌธ์ ์์น๋ฅผ ์ฐพ์ํ ๋ฐํํ ๋ฟ, ์ฌ์ฌ์ฉํ๋ ๊ณผ์ ์ ๊ฑฐ์น์ง ์๋๋ค. ํ์ง๋ง ํผ๋ณด๋์น์์ด์ ์๋์ ๊ฐ์ด ํธ๋ฆฌ๊ตฌ์กฐ๋ก ํจ์๊ฐ ํธ์ถ๋๋ค.
๊ทธ๋ฆผ์์ ๋ณด๋ค์ํผ f(3), f(2), f(1), f(0) ์ฒ๋ผ ๋์ผํ ๋ถ๋ถ๋ฌธ์ ๊ฐ ์ค๋ณต๋๋ค. ์ด๋ ๊ฒ 1ํ๋ง ๊ณ์ฐํ๋ค ๊ทธ๋ค๋ก๋ ์ ์ฅํ์ฌ ๊ฐ์ ์ฌํ์ฉ ํ๋๊ฒ์ด๋ค.
2.Optimal Substructure(์ต์ ๋ถ๋ถ๊ตฌ์กฐ)
๋ถ๋ถ๋ฌธ์ ์ ์ต์ ๊ฒฐ๊ณผ๊ฐ์ ์ฌ์ฉํด ์ ์ฒด๋ฌธ์ ์ ์ต์ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ผ์์๋ ๊ฒฝ์ฐ๋ฅผ ์๋ฏธํ๋ค.์ด๋ ๊ฒ ๋๋ฉด ํน์ ๋ฌธ์ ์ ์ ๋ต์ ๋ฌธ์ ์ ํฌ๊ธฐ์ ์๊ด์์ด ๋์ผํ๋ค.
A - B ๊น์ง์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ๋ ๋ฌธ์ ๊ฐ ์๊ณ , ์ค๊ฐ์ X๊ฐ ์๋ค. ์ผ๋จ ๊ทธ๋ฆผ์ ์ดํด๋ณด์.
๊ทธ๋ฆผ์์ A-X / X-B ๊ฐ ๋ง์ ๊ฒฝ๋ก์ค์ ๊ฐ์ฅ ์งง์ ๊ฒฝ๋ก๋ผ๋ฉด ์ ์ฒด ์ต์ ์ ๊ฒฝ๋ก๋ A - X - B ๊ฐ ๋๋ค.
๋ค์๋งํด์, ๊ทธ๋ฆผ์์ ๋ณผ๋ A -X ์ฌ์ด์ ์ต๋จ๊ฒฝ๋ก๋ AX2 ์ด๊ณ , B - X ์ฌ์ด์ ์ต๋จ๊ฒฝ๋ก๋ BX2 ์ด๋ค. ๋ง์ฝ ๋ค๋ฅธ ๊ฒฝ๋ก๋ฅผ ํํด๋ A - X - B ๋ผ๋ ์ต๋จ๊ฒฝ๋ก๋ ๋ณํ์ง ์๋๋ค. ์ด์ฒ๋ผ ๋ถ๋ถ๋ฌธ์ ์์ ๊ตฌํ ์ต์ ์ ๊ฒฐ๊ณผ๊ฐ ์ ์ฒด ๋ฌธ์ ์์๋ ๋์ผํ๊ฒ ์ ์ฉ๋์ด ๊ฒฐ๊ณผ๊ฐ ๋ณํ์ง ์์๋ DP๋ฅผ ์ฌ์ฉํ ์์๋ค.
DP ์ฌ์ฉ ๊ณผ์
DP๋ ๋ค์ํ ๋ฌธ์ ํด๊ฒฐ์ ์ฌ์ฉ๋ ์์๋ค. ์ฆ, ์ ์ฉํ ์์๋ ๋ฌธ์ ์ธ์ง ํ๋ณํ๋ ๊ฒ์ด ์ค์ํ๊ณ ๊ทธ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ๋ค.
- DP๋ก ํ ์ ์๋ ๋ฌธ์ ์ธ์ง ํ์ธํ๋ค. - ์กฐ๊ฑด์ด ์ถฉ์กฑ๋๋์ง ํ์ธ
- ๋ฌธ์ ๊ฐ์ ๋ณ์๋ฅผ ํ์ ํ๋ค.
- ๋ณ์๊ฐ ๊ด๊ณ์์ ๋ง๋ ๋ค.(์ ํ์) - ํผ๋ณด๋์น์์ f(n) = f(n-1) + f(n-2) ์ฒ๋ผ...!
- ๋ฉ๋ชจํ๋ค.(momoization or tabulation) - ๋ณ์์ ๊ฐ์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋ ๊ฒ
- ๊ธฐ์ ์ํ๋ฅผ ํ์ ํ๋ค. - ๊ฐ์ฅ์์ ๋ฌธ์ ์ ์ํ๋ฅผ ํ์ , ํผ๋ณด๋์น์์ f(0) = 0, f(1) = 1 ์ฒ๋ผ...
- ๊ตฌํํ๋ค. - Buttom-up(๋ฐ๋ณต๋ฌธ) , Top-down(์ฌ๊ท)
๊ตฌํ๋ฐฉ๋ฒ
1. Bottom-Up ๋ฐฉ์(Tabulation)
์ด๋ฆ์ฒ๋ผ ์๋์์๋ถํฐ ๊ณ์ฐ์ ์ํํ๊ณ ๋์ ์์ผ ์ ์ฒด์ ํฐ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ์์ด๋ค. ๋ฉ๋ชจ๋ฅผ ์ํด์ dp๋ผ๋ ๋ฐฐ์ด์ ๋ง๋ค๊ณ ์ด๊ฒ์ 1์ฐจ์์ด๋ผ๊ณ ๊ฐ์ ํ์๋, dp[0]๊ฐ ๊ธฐ์ ์ํ์ด๊ณ , dp[n]์ ๋ชฉํ์ํ๋ก ๋ณด์. Buttom-up ๋ฐฉ์์ dp[0]๋ถํฐ ์์ํ์ฌ ๋ฐ๋ณต๋ฌธ์ ํตํด ์ ํ์์ ๋์ถํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ด์ด dp[n]๊น์ง ๊ฐ์ ์ฌํ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํธ๋ ๋ฐฉ์์ด๋ค. ๋ณดํต ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํ๊ณ , ์ฌ๊ท๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์๋ค.
public static int bottomUp(int num) { //bottom-up dp
//๊ธฐ์ ์ํ๋ฅผ ์ฌ์ ์ ๋ฏธ๋ฆฌ ์ ์ฅ
dp[0] = 0;
dp[1] = 1;
//๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ์ฌ ํ
์ด๋ธ์ ์ฑ์๊ฐ๋ค.
for( int i = 2 ; i <= num ; i++) {
dp[i] = dp[i-1] + dp[i-2];
}
return dp[num];
}
์ฌ๊ธฐ์์ tabulation์ ๋ฉ๋ชจ์ด์ ์ด์ ๊ณผ ๊ฐ๋ค. ๋ฉ๋ชจ๋ฅผ ์ํ ์ ์ฅ๊ฐ์ธ๋ฐ ๋ฐ๋ณต๋ฌธ์ ๋๋ฉด์ dp[0]๋ถํฐ ํ๋์ฉ ์ฑ์ฐ๋ ๊ณผ์ ์ table-filling ์ด๋ผ๊ณ ํ๊ณ ์ด Table์ ์ ์ฅ๋ ๊ฐ์ ์ง์ ์ ๊ทผํ์ฌ ํ์ฉํ๋ฏ๋ก Tabulation ์ด๋ผ๋ ๋ช ์นญ์ด ๋ถ์๋ค๊ณ ํ๋ค.
2. Top-down ๋ฐฉ์(Memoization)
dp[0]์ ๊ธฐ์ ์ํ์์ ์ถ๋ฐํ์ง ์๊ณ , dp[n]์ ๊ฐ์ ์ฐพ๊ธฐ์ํด ์์์ ๋ถํฐ ๋ฐ๋ก ํธ์ถ์ ์์ํ์ฌ, dp[0]๊น์ง ๋ด๋ ค๊ฐ ๋ค์ ํด๋น ๊ฒฐ๊ณผ๊ฐ์ ์ฌ๊ท๋ฅผ ํตํด ์ ์ด์์ผ ์ฌํ์ฉํ๋ ๋ฐฉ์์ด๋ค.
ํผ๋ณด๋์น์ ์์์์์ ํธ๋ฆฌ์์ ๋ดค๋ฏ์ด, n=5์ผ๋ f(3), f(2) ... ๊ฐ ๋ฐ๋ณต์ ์ผ๋ก ๋์ค๊ฒ ๋๋ค. ์ด๋ ์ด๋ฏธ ๊ณ์ฐ์ด ์๋ฃ๋ ๋ถ๋ถ๋ฌธ์ ์ ๊ฒฝ์ฐ ๋ค์ ๋ฌธ์ ๋ฅผ ํธ๋๊ฒ ์๋๋ผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ ๋ด์ญ์ ๊บผ๋ด์ ํ์ฉํ๋ ๊ฒ์ด๋ค. ์ฝ๋๋ฅผ ๋ณด๊ณ ์ดํดํด๋ณด์.
public static int topDown(int num) {
//๊ธฐ์ ์ํ ๋๋ฌ์ 0,1๋ก ์ด๊ธฐํ
if( num <= 0 )return 0;
else if ( num ==1) return 1;
//๋ฉ๋ชจ์ ๊ณ์ฐ๋ ๊ฐ์ด ์์ผ๋ฉด ๋ฐ๋ก ๋ฐํ
if(memo[num]!=0) {
return memo[num];
}
//์ฌ๊ท๋ฅผ ์ฌ์ฉ
memo[num] = topDown(num-1) + topDown(num-2);
return memo[num];
}
Ref.