ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Backtracking] BOJ 2580 μŠ€λ„μΏ 
    Algorithms in Python/baekjoon 2021. 1. 19. 21:27

     

    🎈 λ°±μ€€ 2580 μŠ€λ„μΏ 

    문제

    μŠ€λ„μΏ λŠ” 18μ„ΈκΈ° μŠ€μœ„μŠ€ μˆ˜ν•™μžκ°€ λ§Œλ“  '라틴 μ‚¬κ°ν˜•'μ΄λž‘ νΌμ¦μ—μ„œ μœ λž˜ν•œ κ²ƒμœΌλ‘œ ν˜„μž¬ λ§Žμ€ 인기λ₯Ό λˆ„λ¦¬κ³  μžˆλ‹€. 이 κ²Œμž„μ€ μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 κ°€λ‘œ, μ„Έλ‘œ 각각 9κ°œμ”© 총 81개의 μž‘μ€ 칸으둜 이루어진 μ •μ‚¬κ°ν˜• 판 μœ„μ—μ„œ μ΄λ€„μ§€λŠ”λ°, κ²Œμž„ μ‹œμž‘ μ „ 일뢀 μΉΈμ—λŠ” 1λΆ€ν„° 9κΉŒμ§€μ˜ 숫자 쀑 ν•˜λ‚˜κ°€ μ“°μ—¬ μžˆλ‹€.

    λ‚˜λ¨Έμ§€ 빈 칸을 μ±„μš°λŠ” 방식은 λ‹€μŒκ³Ό κ°™λ‹€.

    1. 각각의 κ°€λ‘œμ€„κ³Ό μ„Έλ‘œμ€„μ—λŠ” 1λΆ€ν„° 9κΉŒμ§€μ˜ μˆ«μžκ°€ ν•œ λ²ˆμ”©λ§Œ λ‚˜νƒ€λ‚˜μ•Ό ν•œλ‹€.
    2. ꡡ은 μ„ μœΌλ‘œ κ΅¬λΆ„λ˜μ–΄ μžˆλŠ” 3x3 μ •μ‚¬κ°ν˜• μ•ˆμ—λ„ 1λΆ€ν„° 9κΉŒμ§€μ˜ μˆ«μžκ°€ ν•œ λ²ˆμ”©λ§Œ λ‚˜νƒ€λ‚˜μ•Ό ν•œλ‹€.

    μœ„μ˜ 예의 경우, 첫째 μ€„μ—λŠ” 1을 μ œμ™Έν•œ λ‚˜λ¨Έμ§€ 2λΆ€ν„° 9κΉŒμ§€μ˜ μˆ«μžλ“€μ΄ 이미 λ‚˜νƒ€λ‚˜ μžˆμœΌλ―€λ‘œ 첫째 쀄 λΉˆμΉΈμ—λŠ” 1이 λ“€μ–΄κ°€μ•Ό ν•œλ‹€.

    λ˜ν•œ μœ„μͺ½ κ°€μš΄λ° μœ„μΉ˜ν•œ 3x3 μ •μ‚¬κ°ν˜•μ˜ κ²½μš°μ—λŠ” 3을 μ œμ™Έν•œ λ‚˜λ¨Έμ§€ μˆ«μžλ“€μ΄ 이미 μ“°μ—¬μžˆμœΌλ―€λ‘œ κ°€μš΄λ° 빈 μΉΈμ—λŠ” 3이 λ“€μ–΄κ°€μ•Ό ν•œλ‹€.

    이와 같이 빈 칸을 μ°¨λ‘€λ‘œ μ±„μ›Œ κ°€λ©΄ λ‹€μŒκ³Ό 같은 μ΅œμ’… κ²°κ³Όλ₯Ό 얻을 수 μžˆλ‹€.

    κ²Œμž„ μ‹œμž‘ μ „ μŠ€λ„μΏ  νŒμ— μ“°μ—¬ μžˆλŠ” μˆ«μžλ“€μ˜ 정보가 μ£Όμ–΄μ§ˆ λ•Œ λͺ¨λ“  빈 칸이 μ±„μ›Œμ§„ μ΅œμ’… λͺ¨μŠ΅μ„ 좜λ ₯ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

    μž…λ ₯

    아홉 쀄에 걸쳐 ν•œ 쀄에 9κ°œμ”© κ²Œμž„ μ‹œμž‘ μ „ μŠ€λ„μΏ νŒ 각 쀄에 μ“°μ—¬ μžˆλŠ” μˆ«μžκ°€ ν•œ μΉΈμ”© λ„μ›Œμ„œ μ°¨λ‘€λ‘œ 주어진닀. μŠ€λ„μΏ  판의 빈 칸의 κ²½μš°μ—λŠ” 0이 주어진닀. μŠ€λ„μΏ  νŒμ„ κ·œμΉ™λŒ€λ‘œ μ±„μšΈ 수 μ—†λŠ” 경우의 μž…λ ₯은 주어지지 μ•ŠλŠ”λ‹€.

    좜λ ₯

    λͺ¨λ“  빈 칸이 μ±„μ›Œμ§„ μŠ€λ„μΏ  판의 μ΅œμ’… λͺ¨μŠ΅μ„ 아홉 쀄에 걸쳐 ν•œ 쀄에 9κ°œμ”© ν•œ μΉΈμ”© λ„μ›Œμ„œ 좜λ ₯ν•œλ‹€.

    μŠ€λ„μΏ  νŒμ„ μ±„μš°λŠ” 방법이 μ—¬λŸΏμΈ κ²½μš°λŠ” κ·Έ 쀑 ν•˜λ‚˜λ§Œμ„ 좜λ ₯ν•œλ‹€.

     


    ❗ 문제의 핡심, 풀이 κ³Όμ •

    0이 μžˆλŠ” μžλ¦¬μ— μ μ ˆν•œ 숫자λ₯Ό μ±„μ›Œλ„£μ–΄μ•Ό ν•œλ‹€.

    => 0이 μžˆλŠ” μ’Œν‘œλ₯Ό μ €μž₯ν•˜λŠ” 리슀트λ₯Ό λ§Œλ“€κ³  각 μ’Œν‘œλŠ” [i, j]둜 μ €μž₯ν•œλ‹€.

     

    0의 μœ„μΉ˜μ—μ„œ ν–‰κ³Ό μ—΄, ꡡ은 μ„ μœΌλ‘œ κ΅¬λΆ„λ˜μ–΄ μžˆλŠ” 3x3 μ •μ‚¬κ°ν˜• μ•ˆμ˜ μˆ«μžλŠ” 1~9κΉŒμ§€ ν•œλ²ˆλ§Œ μ“°μ—¬μ•Ό ν•œλ‹€.

    => 0의 μœ„μΉ˜μ—μ„œ ν–‰, μ—΄, μ •μ‚¬κ°ν˜•(3가지 쑰건)에 μ‘΄μž¬ν•˜λŠ” 숫자 체크가 ν•„μš”ν•˜λ‹€.

         - 1~9 의 μ‘΄μž¬μ—¬λΆ€λ₯Ό νŒλ‹¨ν•˜λŠ” boolean check 리슀트λ₯Ό λ§Œλ“€κ³  False둜 μ΄ˆκΈ°ν™” ν•œλ‹€.

         - 0의 μœ„μΉ˜μ—μ„œ ν–‰, μ—΄, μ •μ‚¬κ°ν˜• 탐색 ν›„ check[숫자] = True둜 λ°”κΎΈμ–΄μ€€λ‹€.

         - μ •μ‚¬κ°ν˜•μ˜ νƒμƒ‰λ²”μœ„λŠ” 0의 μ’Œν‘œκ°€ x, yμΌλ•Œ x // 3 * 3, y // 3 * 3 λΆ€ν„° 3λ§ŒνΌμ΄λ‹€.

     

    • ν•œ 0의 μœ„μΉ˜μ—μ„œ μœ„μ˜ 과정을 톡해 κ³΅ν†΅μœΌλ‘œ 쓰이지 μ•Šμ€ 숫자λ₯Ό μ°Ύμ•˜λ‹€λ©΄ κ·Έ 숫자λ₯Ό λ„£κ³ , λ‹€μŒ 0의 μœ„μΉ˜λ‘œ λ„˜μ–΄κ°€μ„œ 체크λ₯Ό ν•΄μ•Όν•œλ‹€.

    => 0의 μœ„μΉ˜μ—μ„œ ν–‰, μ—΄, μ •μ‚¬κ°ν˜• 탐색 ν›„ 쓰이지 μ•Šμ€ μˆ«μžκ°€ μžˆλ‹€λ©΄, for문을 톡해 쓰이지 μ•Šμ€ 숫자λ₯Ό μ°¨λ‘€λŒ€λ‘œ μŠ€λ„μΏ μ— λ„£μ–΄μ€€λ‹€.

    => 숫자λ₯Ό 0의 μœ„μΉ˜μ— λ„£μ–΄μ£Όκ³ , λ‹€μŒ 0의 index둜 λ„˜μ–΄κ°„λ‹€.

    => λ‹€μŒ 경우의 수λ₯Ό μœ„ν•΄ 넣은 숫자λ₯Ό λ‹€μ‹œ 0으둜 λ°”κΏ”μ€€λ‹€.

     

    λ§Œμ•½ 3가지 쑰건을 λ§Œμ‘±ν•˜λŠ”, 쓰이지 μ•Šμ€ μˆ«μžκ°€ μ—†λ‹€λ©΄ κ·Έ κ²½μš°λŠ” ν‹€λ¦° 것이닀.

    => return을 톡해 λŒμ•„κ°„λ‹€.

     

    μŠ€λ„μΏ  νŒμ„ κ·œμΉ™λŒ€λ‘œ μ±„μšΈ 수 μ—†λŠ” 경우의 μž…λ ₯은 주어지지 μ•ŠλŠ”λ‹€.

    => λ”°λΌμ„œ λΆˆκ°€λŠ₯ν•œ κ²½μš°λŠ” κ³ λ €ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

     

    μ±„μš°λŠ” 방법이 μ—¬λŸΏμΈ κ²½μš°λŠ” κ·Έ 쀑 ν•˜λ‚˜λ§Œμ„ 좜λ ₯ν•œλ‹€.

    => ν•˜λ‚˜μ˜ 경우λ₯Ό 찾으면 λ°”λ‘œ exit(0)으둜 μ’…λ£Œν•œλ‹€.

     

    βœ… 전체 μ½”λ“œ

    import sys
    input = sys.stdin.readline
    
    def go(idx):
        # 0의 μ’Œν‘œ μΈλ±μŠ€κ°€ λ§ˆμ§€λ§‰ + 1 이라면 λ‹€ μ±„μš΄ κ²ƒμ΄λ―€λ‘œ 좜λ ₯ν•œλ‹€.
        if idx == len(zero):
            for i in range(9):
                for j in range(9):
                    print(arr[i][j], end=' ')
                print()
            exit(0)
            return
        
        x, y = zero[idx][0], zero[idx][1]
        check = [False] * 10
    
        for i in range(9):  # ν•œ 열에 μžˆλŠ” 숫자 체크
            check[arr[i][y]] = True
        for j in range(9):  # ν•œ 행에 μžˆλŠ” 숫자 체크
            check[arr[x][j]] = True
        for i in range(x // 3 * 3, x // 3 * 3 + 3):  # 3*3 μ •μ‚¬κ°ν˜• μ•ˆμ— μžˆλŠ” 숫자 체크
            for j in range(y // 3 * 3, y // 3 * 3 + 3):
                check[arr[i][j]] = True
    
        # 3가지 μ‘°κ±΄μ—μ„œ κ³΅ν†΅μœΌλ‘œ 쓰이지 μ•Šμ€ μˆ«μžκ°€ 있으면 λ‹€μŒ 0으둜
        flag = False
        for i in range(1, 10):
            if not check[i]:
                flag = True
                arr[x][y] = i
                go(idx + 1)
                arr[x][y] = 0
    
        # 쓰이지 μ•Šμ€ μˆ«μžκ°€ μ—†μœΌλ©΄ return
        if not flag:
            return
    
    arr = [[]] * 9
    for i in range(9):
        arr[i] = list(map(int, input().split()))
    
    # 0인 μ’Œν‘œλ₯Ό μ €μž₯ν•˜λŠ” 리슀트 μ΄ˆκΈ°ν™”
    zero = []
    for i in range(9):
        for j in range(9):
            if arr[i][j] == 0:
                zero.append([i, j])
    go(0)

     

    λŒ“κΈ€

Designed by Tistory.