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์„ ์ด์šฉํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ ˆ์ฐจ

  1. ์ƒํƒœ ๊ณต๊ฐ„ ํŠธ๋ฆฌ์˜ DFS (๊นŠ์ด ์šฐ์„  ๊ฒ€์ƒ‰)์„ ์‹ค์‹œํ•œ๋‹ค

  2. ๊ฐ node๊ฐ€ ์œ ๋งํ•œ์ง€๋ฅผ ์ ๊ฒ€ํ•œ๋‹ค

  3. ๋งŒ์ผ ๊ทธ 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?