์ํ ์๊ฐ๋ฝ(?)
1์ฃผ์ฐจ๊ฐ ๋๋๊ณ ์ด์์ง ๋ถ๋ค์ด ์ฐธ์ํ์ ํฐํ์์์ ํ ๋ถ์ด ์ง๋ฌธ์ ํ์ จ๋ค.
"์ฌ๊ทํจ์๊ฐ ๋ง์ด ํท๊ฐ๋ฆฌ๋๋ฐ ํ์ ์์๋ ๋ง์ด ์ฌ์ฉํ๋์?"
๋ํ๋ ๋ต๋ณ.
'๋ํ๊ธฐ ๋ง์ด ์จ์?' ๊ฐ์ ์ง๋ฌธ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ์.
(์.)
์ธ์ ๊ฐ ์ ๋ฆฌ๋ฅผ ํด๋ณด๊ณ ์ถ์๋ค.
์ฌ์ด ๋ฌธ์ ๋ค์ ํ๋ฉด์ ๋ณด์๋ ํจํด์ด๋, ๋ฐฑํธ๋ํน, ๋ถํ ์ ๋ณต ๊ฐ์ ๊ฐ๋
๋ ๊ฐ๋จํ ์ ๋ฆฌํด๋ณด๊ณ ์ ํ๋ค.
ํ์ด์ฌ ์ฑ
(Do it! ์๋ฆฌ์ฆ)์ ์ฐธ๊ณ ํ๋ค.
๋๋ ์ฌ๊ท๋ฅผ ๋ค์๊ณผ ๊ฐ์ ๋น์ ์ ์ํฉ์ผ๋ก ์ดํดํ๋ค.
- ์ ์ฒด ๋ฌธ์ ์ํฉ์์ ์ฒ๋ฆฌํด์ผํ ๋ฒ์๋ฅผ ๋ถํ ํด์ ๊ฐ๊ฐ์ ๋ ๋๊ธฐ๊ฑฐ๋, ๋๋ ์ต์๋จ์ ํ๋๋ง ์ฑ๊ธฐ๊ณ ๋๋จธ์ง๋ฅผ ๋ค์ ๋ ๋๊ธด๋ค.
- ๋ ๋๊ธฐ๋ค ๋จ์ ๋ฌธ์ ์ํฉ์ด ์ต์๋จ์ ํ๋๊ฐ ๋๋ฉด
๊ทธ๋ ์๋ง์ ๋ฐํ๊ฐ์๋ฐํ
ํ๊ฑฐ๋์ ์ฅ
(์ธ๋ถ์ ์ ์ธ๋ ๋ฐฐ์ด, ๋ณ์ ๋ฑ์)ํ๋ค.
์์ ๊ทธ๋ฆผ์ 2๋ฒ์์์ ๋ฐํ
์ํฉ์ ๋๊ฐ์ง ์ข
๋ฅ๋ฅผ ๋ณด์ฌ์ค๋ค.
์ผ์ชฝ ๊ทธ๋ฆผ์ ์ํฅ์์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๊ณ์ฐํ๋ค. ์ต์๋จ์(Terminating case, Base case)์์ ๋ฐํํ ๊ฐ์, ๋ฐ๋ก ์ ์ฌ๊ทํธ์ถ์ด ์์ ์ด ๊ฐ์ง๊ณ ์๋ ํ๋์ ํจ๊ป ๊ณ์ฐํด์ ๋ค์ ๋ฐํํ๋ค.
๊ทธ ๊ณผ์ ์ด ๋ฐ๋ณต๋๋ฉด ์ต์ด ์ฌ๊ทํธ์ถ์ ๋ฐํ๊ฐ์ด ์ ์ฒด ๋ฌธ์ ์ํฉ์ ํด๊ฒฐ๊ฐ์ด ๋๋ ๊ฒ์ด๋ค.
์ค๋ฅธ์ชฝ ๊ทธ๋ฆผ์ ํํฅ์์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๊ณ์ฐํ๋ค. ์ ์ฒด ๋ฌธ์ ์ํฉ์ ํด๊ฒฐ๊ฐ์ ์ ์ฅํ๋ paramter ์๋ฆฌ๋ฅผ ํ๋ ๋ง๋ค๊ณ , ์๋ ์ฌ๊ท์๊ฒ ์์ ์ด ๊ฐ์ง๊ณ ์๋ ํ๋๋ฅผ ์ถ๊ฐ(๋๋ ํ์ํ ์ฐ์ฐ)ํ ๊ฐ์ ์ ๋ฌํ๋ค. ์ด ๊ณผ์ ์ด ๋ฐ๋ณต๋๋ฉด์ ์ฌ๊ท์ ๋ฐ๋ฐ๋ฅ(์ต์๋จ์๊น์ง ์ฐ์ฐ ์๋ฃ ๋ ํ)์ ๋์ฐฉํ์ ๋๋, ๋ฐ๋ก ์ ์ฌ๊ท์์ ๋ณด๋ด์ค ๊ฐ์ด ๊ณง ์ ์ฒด ๋ฌธ์ ์ํฉ์ ํด๊ฒฐ๊ฐ์ด ๋๋ค. ๋ฐ๋ก ๊ทธ ๊ฐ์ด ์ฌ๊ท๋ฅผ ํ์ถํ๋ฉด์ ์ฐ์์ ์ผ๋ก ๋ฐํ๋๊ฒ ๋๊ณ , ์ต์ด ์ฌ๊ท ํธ์ถ์ ๋ฐํ๊ฐ์ด ์ต์๋จ์์์ ๋ฐํํ ๊ทธ ๊ฐ์ด ๋๋ค.
์ฝ๋๋ก ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
# ์ผ์ชฝ (์ํฅ์)
def sumVector(A, n):
if n == 1:
return A[0]
else:
return A[n-1] + sumVector(A,n-1)
# ์ค๋ฅธ์ชฝ (ํํฅ์)
def sumVector(B, n, sum):
if n == 0:
return sum
else:
return sumVector(B,n-1,sum+B[n-1])
์ค๋ฅธ์ชฝ์ ๊ฒฝ์ฐ๋ฅผ ๊ผฌ๋ฆฌ ์ฌ๊ท(tail recursion)๋ผ๊ณ ๋ ํ๋ค. ๋ง์ฝ ์ปดํ์ผ๋ฌ๊ฐ ๊ผฌ๋ฆฌ ์ฌ๊ท ์ต์ ํ๋ฅผ ์ง์ํ๋ค๋ฉด, ๊ผฌ๋ฆฌ ์ฌ๊ท๋ ์ฐ์์ ์ธ ์ฌ๊ท ํธ์ถ๋ก ์ผ์ด๋๋ stack์ ์ค๋ฒํค๋๋ฅผ ์ค์ผ ์ ์๋ค.
์ฌ๊ท ํธ์ถ์ด ํจ์ ๋ด์ ๋๋ฒ ์ผ์ด๋ ์๋ ์๋ค. ์ฑ ์์๋ ๋ค์์ ์ฌ๊ทํจ์๋ฅผ ์๊ฐํ๋ค.
def recur(n):
if n > 0:
recur(n - 1)
print(n)
recur(n - 2)
์ค๋ฌํ๊ฒ๋ ์ด๋ฌํ ์ฌ๊ท ํธ์ถ์ ๋น์ฌ๊ท์ ์ผ๋ก ๋ฐ๊พธ๋ ๊ณผ์ ์์ ํจ์๋ฅผ ์ดํดํ ์ ์๋ค.
1. ๋ค์ ๋์ค๋ ์ฌ๊ท
๋จผ์ ๋ค์ ๋์ค๋ ์ฌ๊ท recur(n - 2)
๋ฅผ ์์ ๋ณด์. ํด๋น ํธ์ถ์ ์ด๋ฐ ์๋ฏธ์ด๋ค.
์ธ์๋ก
n-2
์ ๊ฐ์ ์ ๋ฌํ๊ณrecur( )
ํจ์๋ฅผ ํธ์ถํด๋ผ.
์ฌ๊ท๋ฅผ ์์ค๋ค๋ ๊ฒ์ recur()
ํจ์์ ํธ์ถ์ ์์ค๋ค๋ ๊ฒ. ๋ฐ๋ผ์ ์๋์ ๊ฐ์ ๋ฐฉ์์ด ์๋ค.
n
์ ๊ฐ์n -2
๋ก ์ ๋ฐ์ดํธ ํ ํ, ํจ์์ ์์์ง์ ์ผ๋ก ๋์๊ฐ๋ฉด ๋๋ค.
์ด๋ฅผ ์ ์ฉํ ์ฝ๋์ด๋ค.
def recur(n):
while n > 0:
recur(n - 1)
print(n)
n = n - 2 # ์
๋ฐ์ดํธ ํํ, while ๋ฐ๋ณต๋ฌธ ๋ค์ ๋ฃจํ.(์์์ง์ ์ผ๋ก ๋์๊ฐ๊ธฐ)
2. ์์ ๋์ค๋ ์ฌ๊ท
์์ ๋ฑ์ฅํ๋ ์ฌ๊ท๋ ์์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก๋ ์ ๊ฑฐํ ์ ์๋ค.
์๋ํ๋ฉด n
๊ฐ์ ์
๋ฐ์ดํธ(n = n - 1
)ํ๊ณ ์์์ง์ ์ผ๋ก ๋์๊ฐ๋ฉด, print(n)
์ด ์ฌ๋ฐ๋ฅด๊ฒ ์คํ ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ค์ ๋งํด, ํ์ฌ ๋ฃจํ์ n
์ ๊ฐ์ ์์๋ก ์ ์ฅํด์ผ ํ๋ค. ๊ทธ๋์ recur(n - 1)
์ ์ฒ๋ฆฌ๋ฅผ ๋๋ธ ํ์ ์ ์ฅํ๋ n
์ ๊ฐ์ ๊บผ๋ด print(n)
ํด์ค์ผ ํ๋ค.
๊ฒฐ๊ตญ ์คํ์ ์ฌ์ฉํ์ฌ n์ ๊ฐ์ ์ ์ฅํด์ผ ํ๋ค.
์ด๋ฅผ ์ ์ฉํ ์ฝ๋์ด๋ค.
from collections import deque
def recur(n):
stk = deque() # ์คํ์ผ๋ก ์ฌ์ฉํ ๋ฑ.
while True:
while n > 0:
stk.append(n) # ์คํ์ n๋ถํฐ 1์ฉ ์ค์ฌ๋๊ฐ๋ฉด์ ์ ์ฅ. ํ์ฌ ๋ฃจํ์ 'n'์ ์ ์ฅํ๋ค๋ ์๋ฏธ.
n = n - 1
if stk:
n = stk.pop()
print(n)
n = n - 2 # ์
๋ฐ์ดํธ ํํ, while ๋ฐ๋ณต๋ฌธ ๋ค์ ๋ฃจํ.(์์์ง์ ์ผ๋ก ๋์๊ฐ๊ธฐ)
continue # ๋ฌดํ while๋ก ๋ณต๊ท
break
์คํ ์ ์ฅ ๊ณผ์ ์ด ๋๋๊ณ , stk.pop()
์ ํตํด ๋งจ ์์ ๊ฐ(๊ฐ์ฅ ์์ ๊ฐ์ด ๋๊ฒ ๋ค. ์ฌ๊ธฐ์๋ 1)์ ๊บผ๋ธ๋ค, ํ๋ฆฐํธ ํ๊ณ , n = n - 2
๋ฅผ ํด์ ์์์ ์ผ๋ก ๋์์ค๋ฉด ์๊น ๊ทธ ์คํ์ ๋ค์ ๊ฐ๋ค์ ์๋๋ค. ์ฆ, ํธ์ถ ์์๊ฐ ์ง์ผ์ง๋ ๊ฒ์ด๋ค.
๋ํด๋ ์น์ ์ ์ ์์ ์ ๋ํ๋ค. ๊ฐ๊ดํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- Divide an instance of a problem into one or more smaller instances.
- Conquer(solve) each of the smaller instances. Unless a smaller instance is sufficiently small, use
recursion
to do this.- If necessary, combine the solutions to the smaller instances to obtain the solution to the original instance.
ํฐ ์ฌ์ด์ฆ์ ๋ฌธ์ instance๋ฅผ ์ต๋ํ ์๊ฒ ๋๋์ด ๊ฐ๊ฐ ํด๊ฒฐํ๋ค. ๊ทธ๋ฆฌ๊ณ ํ์์ ๋ฐ๋ผ ์ด ๊ฒฐ๊ณผ๋ค์ combineํ๋ค. ์ต๋ํ ์๊ฒ ๋๋์ด ํด๊ฒฐ ํ๋ ๊ณผ์ ์์ ์ฌ๊ท์ ์ธ ๋ฐฉ๋ฒ์ด ์ฐ์ธ๋ค.
๊ทธ๋ ๊ฒ ํฌ์ง ์์ ์ฌ์ด์ฆ์ ๋ฌธ์ ์์๋ ์ ์ฉํ์ง ์์ ์ ์๋ค.
๋ํ์ ์ธ ํ์ฉ์ผ๋ก๋ ์ด์ง ํ์
, ๋ณํฉ ์ ๋ ฌ
, ํต ์ ๋ ฌ
, ํ๋ ฌ ๊ณฑ์
, ์ต๊ทผ์ ์ ์ ์(closest Pair Problem)
์ด ์๋ค.
์๋๋ N-queen ๋ฌธ์ ์ ์ํ ๊ณต๊ฐ ํธ๋ฆฌ.
๋ฐฑํธ๋ํน(back-tracking)์ด๋ ์ํ ๊ณต๊ฐ ํธ๋ฆฌ(state space tree)๋ฅผ ํ์ํ๋ ๊ธฐ๋ฒ ์ค ํ๋.
๋ค์๊ณผ ๊ฐ์ ํ์ ๊ธฐ๋ฒ๋ค์ด ์๋ค.
0. Brute Force Method
๋ง ๊ทธ๋๋ก ์ง์น๊ฐ์ด ๋ฌด์ํ๊ฒ ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ๋ค ๊ฒ์ฌํด๋ณด๋ ๋ฐฉ๋ฒ์ด๋ค. ์กฐ๊ธ ์ ์ ๋ ๋ง๋ก๋
Solution space๋ฅผ ๋ชจ๋ ํ์ํ์ฌ ํด๋ฅผ ์ป๋ ๋ฐฉ๋ฒ์ด๋ค. instance์ ์ฌ์ด์ฆ๊ฐ ์์ ๊ฒฝ์ฐ ์ค๋ฒํค๋๊ฐ ์ ์ด ํจ์จ์ ์ด๋ค.
1. ์์ ํ์(Exhaustive Search)
๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ๋ค ๊ฒ์ฌํ์ฌ ํด๋ฅผ ์ฐพ๋ ๋ฐฉ๋ฒ์ด๋ค. Brute Force Method์ ์ผ์ข ์ผ๋ก, ๊ฑฐ์ ๊ฐ์ ์๋ฏธ๋ก ์ฐ์ธ๋ค. ๋ณดํต ์์ ํ์์ ์์ด์ด๋ ์กฐํฉ(permutational or combinational-related)์ผ๋ก ๊ฒฝ์ฐ์ ์๋ฅผ ์์ฑํด์ ์ ๋ถ ํ์ํ๋ ๊ฒฝ์ฐ๋ฅผ ์๋ฏธํ๋ค.It is a brute-force approach to deal with combinatorial problems (permutations, combinations). In this approach, we generate each element in the problem and then select the ones that satisfy all the constraints, and finally find a desired element.
...
์ถ์ฒ: https://towardsdev.com/brute-force-and-exhaustive-search-f431484e5293
2. ๋ฐฑํธ๋ํน(Backtracking)
์์ ํ์์ ๋ฐฉ๋ฒ๊ณผ ์ ์ฌํ์ง๋ง, ๊ฐ์ง์น๊ธฐ(pruning)๋ฅผ ํ์ฌ ๋ ํจ์จ์ ์ด๋ค.
์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๋ถ๊ธฐ์์ '๋งํ๋ฉด'(= not promising ํ๋ฉด = ์ด ๋ถ๊ธฐ์ ํ์ ํ์์ด ์๋ฏธ๊ฐ ์์ผ๋ฉด) ๊ทธ ํ์ ๋ถ๊ธฐ๋ฅผ ํ์ํ์ง ์๋๋ค.
promising ํจ์๋ฅผ ๋ฐ๋ก ๊ตฌํํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. DFS(Depth-First-Search)๋ก ๊ตฌํ.
3. ๋ถ๊ธฐ ํ์ ๊ธฐ๋ฒ(Branch & Bound)
๋ฐฑํธ๋ํน์์ '๊ฐ์ง์น๊ธฐ'์ ๊ธฐ์ค ์ฆ, promisingํจ์์ ํ์ ์ด ์ํ ๊ณต๊ฐ ํธ๋ฆฌ ๊ฐ ๋ ธ๋์ ํ์ ๊ฐ์ ์์กดํ๋ค. ๋ฐฑํธ๋ํน ๊ธฐ๋ฒ๋ณด๋ค ๋น ๋ฅด๊ฒ ํด๋ฅผ ์ฐพ๋๋ค. ๊ฐ์ฅ ์ฐ์ํ ํ์ ๊ฐ์ ๊ฐ์ง ๋ ธ๋๋ฅผ ๋จผ์ ํ์ํ๋ ์ต์ฐ์ ํ์(Best First Search)์ผ๋ก ํด๋ฅผ ์ฐพ๋๋ค. Best Fisrt Search์ Breadth First Search์ ์ฐจ์ด์ ์ (์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ).
๋์ ๊ณํ๋ฒ
์ต์ ๋ถ๋ถ ๊ตฌ์กฐ (Optimal Substructure)
๋ฉ๋ชจ์ด์ ์ด์ (memoization)
'์ด๋ฏธ ๊ณ์ฐ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ' โก๏ธ ๋ฉ๋ชจ์ด์ ์ด์
ํจ์์ ๋ฐํ๊ฐ DP ํ ์ด๋ธ์(์ฃผ๋ก ๋ฐฐ์ด) ์บ์ฑ.
ํ์ง๋ง ๋ฉ๋ชจ์ด์ ์ด์
๊ณผ DP๋ ๋ณ๊ฐ์ ๊ฐ๋
.
ํ๋ค์ด ๋ฐฉ์์์ ๋ฉ๋ชจ์ด์ ์ด์
์ '์ฌ์ฉ'ํ๋ ๊ฒ ๋ฟ.
ํ๋ค์ด(์ฌ๊ท) vs ๋ฐํ ์ (๋ฐ๋ณต๋ฌธ)
ํ๋ค์ด์ ์ฌ๊ทํธ์ถ์์ ์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๋งค์ฐ ๋ง์ ๋ถ๊ธฐ๊ฐ ์๊ธธ ์ ์์ง๋ง, ๋ฉ๋ชจํด๋ ๊ฐ์ ์ป์ด์์ ํ์ ๋ถ๊ธฐ๋ฅผ ์์ฑํ์ง ์๋๋ค.
๋ฐํ ์ ๋ฐฉ์์์๋ ์ ํ์์ ์ถฉ์คํ๊ฒ ๋ฐฐ์ด์ ์ผ์ชฝ๋ถํฐ ์ฑ์๋๊ฐ๋ค. ๋ฉ๋ชจ์ด์ ์ด์ ๊ณผ๋ ์ด์ง ๋ค๋ฅด๋ค.
์ ํ์ ํํ๋ ๋ฐํ
์
.
์ฐ์ตํ๊ธฐ์๋ ํ๋ค์ด์ด ์ข๋ค.(์ฝ์น๋)
๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ vs ๋ถํ ์ ๋ณต
'๋ถ๋ถ ๋ฌธ์ ์ ์ค๋ณต' ์ฌ๋ถ์ ์ฐจ์ด
ํผ๋ณด๋์น ์์ด
์ญ์ ํผ๋ณด๋์น ์์ด์ด ๊ฐ์ฅ ์ข์ ์์.
โฌ๏ธ ์์ ๊ทธ๋ฆผ์ ๋ฉ๋ชจ์ด์ ์ด์
์์ด ์ฌ๊ทํธ์ถ์ ๊ณ์ํ๋ ๊ฒฝ์ฐ.
โฌ๏ธ ์๋๋ ํ๋ค์ด ๋ฐฉ์์ DP๋ฅผ ํตํด(/w ๋ฉ๋ชจ์ด์ ์ด์
) ํ์ ๋ถ๊ธฐ๋ฅผ ์์ฑํ์ง ์๊ฒ ๋๋ ๊ฒฝ์ฐ.
๐ ํ์ด์ฌ ์ฝ๋ (ํผ๋ณด๋์น ์์ด 99๋ฒ์งธ ํญ ๊ตฌํ๊ธฐ).
# dp ํ
์ด๋ธ
d = [0] * 100
###############################################################
# ํ๋ค์ด ๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ
# ์ฌ๊ทํจ์์ ๋ฉ๋ชจ์ด์ ์ด์
์ผ๋ก ๊ตฌํ
def fibo(x):
if x==1 or x==2 :
return 1
# ์ด๋ฏธ ๊ฐ์ด ๊ตฌํด์ ธ ์๋ ๊ฒฝ์ฐ ๊ทธ ๊ฐ์ ๋ฐํ
if d[x] != 0:
return d[x]
# ์๋๋ผ๋ฉด ์ ํ์ ๋ฐ๋ผ ์ฌ๊ทํธ์ถ
d[x] = fibo(x-1) + fibo(x-2)
return d[x]
print(fibo(99))
###############################################################
# ๋ฐํ
์
๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ
# ๋ฐ๋ณต๋ฌธ์ ์ด์ฉ
# dp ํ
์ด๋ธ ์ด๊ธฐํ
d = [0] * 100
# ์ฒซ ๊ฐ(?)
d[1] = 1
d[2] = 1
n = 99
for i in range(3, n+1):
d[i] = d[i-1] + d[i-2]
print(d[n])
์ฐธ๊ณ ํ์ด์ง