Backtracking
Backtracking ๊ฐ๋
์ฌ๋ฌ ๊ฐ์ง ์ ํ์ง๋ค์ด ์กด์ฌํ๋ ์ํฉ์์ ํ๊ฐ์ง๋ฅผ ์ ํ
์ ํ์ด ์ด๋ฃจ์ด์ง๋ฉด ์๋ก์ด ์ ํ์ง๋ค์ ์งํฉ์ด ์์ฑ๋จ
์ด๋ฐ ์ ํ์ ๋ฐ๋ณตํ๋ฉด์ ์ต์ข ์ํ์ ๋๋ฌ
์ฌ๋ฐ๋ฅธ ์ ํ์ ๊ณ์ํ๋ฉด ๋ชฉํ ์ํ(goal state)์ ๋๋ฌํ๋ค!
Backtracking๊ณผ DFS์ ์ฐจ์ด
์ด๋ค node์์ ์ถ๋ฐํ๋ ๊ฒฝ๋ก๊ฐ ํด๊ฒฐ์ฑ ์ผ๋ก ์ด์ด์ง ๊ฒ ๊ฐ์ง ์์ผ๋ฉด ๋ ์ด์ ๊ทธ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ๊ฐ์ง ์์์ผ๋ก์จ ์๋์ ํ์๋ฅผ ์ค์
Prunning (๊ฐ์ง์น๊ธฐ)
DFS๊ฐ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ์ถ์ ํ๋๋ฐ ๋นํด Backtacking์ ๋ถํ์ํ ๊ฒฝ๋ก๋ฅผ ์กฐ๊ธฐ์ ์ฐจ๋จํจ
DFS๋ฅผ ํ๊ธฐ์๋ ๊ฒฝ์ฐ์ ์๊ฐ ๋๋ฌด ๋ง์ ๋
N! ๊ฐ์ง์ ๊ฒฝ์ฐ์ ์๋ฅผ ๊ฐ์ง ๋ฌธ์ ์ ๋ํด DFS๋ฅผ ํ๋ฉด ์ฒ๋ฆฌ ๋ถ๊ฐ๋ฅํ๋ค
Back Tracking ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก ๊ฒฝ์ฐ์ ์๊ฐ ์ค์ด๋ค์ง๋ง, ์ด ์ญ์ ์ต์ ์ ๊ฒฝ์ฐ์๋ ์ฌ์ ํ ์ง์ํจ์ ์๊ฐ (Exponential Time)์ ์ํ๋ฏ๋ก ์ฒ๋ฆฌ ๋ถ๊ฐ๋ฅ
Root node์์ Leaf node ๊น์ง์ ๊ฒฝ๋ก๋ ํด๋ต ํ๋ณด (candidate solution)๊ฐ ๋๋๋ฐ, DFS๋ฅผ ํ์ฌ ๊ทธ ํด๋ต ํ๋ณด ์ค์์ ํด๋ต์ ์ฐพ์ ์ ์์
but, ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ํด๋ต์ด ๋ ๊ฐ๋ฅ์ฑ์ด ์ ํ ์๋ node์ ์์ node (descendant) ๋ค๋ ๋ชจ๋ ๊ฒ์ํด์ผ ํ๋ฏ๋ก ๋นํจ์จ์
Backtracking ๊ธฐ๋ฒ
์ด๋ค node์ ์ ๋ง์ฑ์ ์ ๊ฒํ ํ์ ์ ๋ง(promising) ํ์ง ์๋ค๊ณ ๊ฒฐ์ ๋๋ฉด ๊ทธ node์ ๋ถ๋ชจ๋ก ๋๋์๊ฐ์ (
backtracking
) ๋ค์ ์์ node๋ก ๊ฐ์ด๋ค node๋ฅผ ๋ฐฉ๋ฌธํ์์ ๋
๊ทธ node๋ฅผ ํฌํจํ ๊ฒฝ๋ก๊ฐ ํด๋ต์ด ๋ ์ ์์ผ๋ฉด ๊ทธ node๋ ์ ๋งํ์ง ์๋ค๊ณ ํจ
ํด๋ต์ด ๊ฐ๋ฅ์ฑ์ด ์์ผ๋ช ์ ๋งํ๋ค๊ณ ํจ
๊ฐ์ง์น๊ธฐ (prunning)
: ์ ๋งํ์ง ์์ node๊ฐ ํฌํจ๋ ๊ฒฝ๋ก๋ ๋ ์ด์ ๊ณ ๋ คํ์ง ์๋๋ค
Backtracking์ ์ด์ฉํ ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฐจ
์ํ ๊ณต๊ฐ ํธ๋ฆฌ์ DFS (๊น์ด ์ฐ์ ๊ฒ์)์ ์ค์ํ๋ค
๊ฐ node๊ฐ ์ ๋งํ์ง๋ฅผ ์ ๊ฒํ๋ค
๋ง์ผ ๊ทธ node๊ฐ ์ ๋งํ์ง ์์ผ๋ฉด, ๊ทธ node์ ๋ถ๋ชจ node๋ก ๋์๊ฐ์ ๊ฒ์์ ๊ณ์ํ๋ค
N-Queen ๋ฌธ์
SWEA 2806
def backtrack(idx): #idx = ํ
global N, cnt
# ์ต์ข
์ํ์ธ์ง ํ์ธํ๊ณ , ์ต์ข
์ํ์ด๋ฉด ํด
if idx == N:
# ๋ค ์ฐพ์์ - ํด!
cnt +=1
return
# ํด๋น ์ํ์์ ์ ํํ ์ ์๋ ํ๋ณด๊ตฐ ์์ฑ
# Node๊ฐ ์ ๋งํ์ง ํ์ธ : ์ด / ์ํฅ ๋๊ฐ / ํํฅ ๋๊ฐ ํ์ธ
for i in range(N):
# if ์ด์ด ์ ๋งํ๊ณ , ๋๊ฐ๋ค์ด ์ ๋ง
if not col[i] and not dia_1[idx +i] and not dia_2[N+i-idx-1]:
# ๋ชจ๋ ํ๋ณด๊ตฐ์ ๋ํด์ ๋ค์ ์ํ ์คํ
col[i] = 1
dia_1[idx+i] = 1
dia_2[N+i-idx-1] = 1
# ํ์ ์ฆ๊ฐ์ํค๊ธฐ
backtrack(idx+1)
# ๋ค์ ์ฌ์ฉํ ๊ฒ์ ์์ ์ค
col[i] = 0
dia_1[idx+i] = 0
dia_2[N+i-idx-1] = 0
T = int(input())
for t in range(1, T+1):
N = int(input())
# ๊ฐ ํ์๋ 1๊ฐ์ Queen๋ง ์ฌ ์ ์์
col = [0] * N # ์ด์ ์ฌ์ฉ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ ๋ฆฌ์คํธ
# ๋๊ฐ ์ ๋ง์ฑ์ ํ๋จํ ๋ฆฌ์คํธ
# ์ํฅ ๋๊ฐ: i์ j์ ํฉ์ด ๊ฐ์
dia_1 = [0] * (2*N -1) # (r+c) ๋ก ๋๊ฐ์ ๋ฒํธ ๋งค๊น
# ํํฅ ๋๊ฐ: i-j ์ฐจ๊ฐ ์ผ์
dia_2 = [0] * (2*N -1) # (N + c -r -1) ๋ก ๋๊ฐ์ ๋ฒํธ ๋งค๊น
cnt = 0
backtrack(0)
print('#{} {}'.format(t,cnt))
Subset
๋ถ๋ถ์งํฉ ๊ตฌํ๊ธฐ
ex)
# {1,2,3,4,5,6,7,8,9,10} ์ powerset ์ค ์์ใ
ก์ด ๊ฐ์ด 10์ธ ๋ถ๋ถ์งํฉ์ ๋ชจ๋ ์ถ๋ ฅํ์์ค.
def backtrack(arr, idx, N, selected, sum_num):
if sum_num > 10:
return
if idx == N:
# ์ดํฉ์ด 10์ด๋ฉด ์ถ๋ ฅ
if sum_num == 10:
for i in range(N):
if selected[i]:
print(arr[i], end=' ')
print()
return
#ํ์ฌ index๋ฅผ ์ ํ ํ์ ๊ฒฝ์ฐ
selected[idx] =1
backtrack(arr, idx+1, N, selected, sum_num + arr[idx])
#ํ์ฌ index ๋ฅผ ์ ํํ์ง ์์์ ๊ฒฝ์ฐ
selected[idx] = 0
backtrack(arr, idx+1, N, selected, sum_num )
arr = [1,2,3,4,5,6,7,8,9,10]
backtrack(arr, 0, 10, [0]*10, 0)
Space State Tree๋ฅผ ๊ตฌ์ถํ์ฌ ๋ฌธ์ ํด๊ฒฐํ๊ธฐ
Backtracking์ ์ด์ฉํ์ฌ ์์ด ๊ตฌํ๊ธฐ
์ ๊ทผ ๋ฐฉ๋ฒ์ ๋ถ๋ถ์งํฉ ๊ตฌํ๋ ๋ฐฉ๋ฒ๊ณผ ์ ์ฌ
ex)
def backtrack(result, selected, idx, N):
if idx == N:
print(result)
return
# ์ฌ์ฉ ๊ฐ๋ฅํ ์ ํ์ง ํ๋ณด๊ตฐ์ ๋ํ์ฌ ๋ค์ ๋จ๊ณ๋ก ์งํ
for i in range(N):
if not selected[i]:
selected[i] = 1
result[idx] = i
backtrack(result, selected, idx+1, N)
selected[i] = 0
N = 5
backtrack([0]*N, [0]*N, 0, N)
Last updated
Was this helpful?