ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 17406 배열 돌리기4
    Algorithm/BOJ 2021. 3. 29. 14:00
    728x90

    출처: www.acmicpc.net/problem/17406

    분류: 완전탐색


    접근방식

    주어진 rcs 의 순열을 뽑아주고 주어진 대로 잘 구현하면 되는 문제였습니다.

    아직 순열이 익숙하지 않으시다면 여기로 :)

     

    완전탐색의 문제는 늘 그렇죠. 알겠는데 어케 구현하냐.......

    머리가 안 돌아가서 배열 돌리는 데 한참이 걸렸습니다 😭

    이건 뭐 다른 방법보다 직접 해보면서 익숙해지는 게 최선 같아요

    저는 미리 회전할 부분을 카피해놓고 사이즈별로 위, 아래, 오른쪽, 왼쪽을 각각 포문돌면서 밀어주는 방식으로 구현했씁니다.

     

    처음에 회전할 부분만 그 크기만큼의 배열로 복사해놓고, 그부분을 또 계산해서 하는 방식으로 했는데요...

    그냥 굳이 다른 크기의 배열에 힘들게 복사해서 계산하지 말고 원복 배열을 그대로 카피해놓고 하면 훨씬 간단하면서도 빠르게 구할 수 있습니다...

    하 전 왜 이렇게 했을까요 😳🤯

    처음에 회전할 크기만큼 복사해놓고 하기 ( 248ms )

    func rotate(_ rcs: [Int], metrix: inout [[Int]]) {
        let row = rcs[0]-1
        let col = rcs[1]-1
        let size = rcs[2]
        
        var origin = [[Int]](repeating: [Int](repeating: 0, count: rcs[2]*2+1), count: rcs[2]*2+1)
        
        for r in 0..<origin.count {
            for c in 0..<origin.count {
                origin[r][c] = metrix[r+row-rcs[2]][c+col-rcs[2]]
            }
        }
        
        for s in 1...rcs[2] {
            // 위
            for originC in size-s..<origin.count-size+s-1 {
                metrix[row-s][(originC + col-size) + 1] = origin[size-s][originC]
            }
            
            // 아래
            for originC in (size-s+1..<origin.count-size+s).reversed() {
                metrix[row+s][(originC + col-size) - 1] = origin[size+s][originC]
            }
            
            // 오른쪽
            for originR in size-s..<origin.count-size+s-1 {
                metrix[(originR + row-size) + 1][col+s] = origin[originR][size+s]
            }
            
            // 왼쪽
            for originR in (size-s+1..<origin.count-size+s).reversed() {
                metrix[(originR + row-size) - 1][col-s] = origin[originR][size-s]
            }
        }
    }

     

    그냥 원본 배열 복사 ( 60 ms )

    시간도 훨씬 짧고 코드도 훨씬 간단하죠.... 

    func rotate(_ rcs: [Int], metrix: inout [[Int]]) {
        let row = rcs[0]-1
        let col = rcs[1]-1
        
        let origin = metrix
        
        for s in 1...rcs[2] {
            // 위
            for c in col-s..<col+s {
                metrix[row-s][c+1] = origin[row-s][c]
            }
            
            // 아래
            for c in (col-s+1...col+s).reversed() {
                metrix[row+s][c-1] = origin[row+s][c]
            }
            
            // 오른쪽
            for r in row-s..<row+s {
                metrix[r+1][col+s] = origin[r][col+s]
            }
            
            // 왼쪽
            for r in (row-s+1...row+s).reversed() {
                metrix[r-1][col-s] = origin[r][col-s]
            }
        }
    }

     

    (크게크게 보기... 메모 ... ✍️)

     

    이렇게 회전 함수를 구현했다면 rcs 의 순열 대로 회전시키고 결과 값을 구해주면 됩니다!

     

    해결방법

    let nmk = readLine()!.split(separator: " ").map { Int(String($0))! }
    var metrix = [[Int]]()
    var rcsList = [[Int]]()
    var minResult = 50 * 50 * 101
    
    for _ in 0..<nmk[0] {
        metrix.append(readLine()!.split(separator: " ").map { Int(String($0))! })
    }
    
    for _ in 0..<nmk[2] {
        rcsList.append(readLine()!.split(separator: " ").map { Int(String($0))! })
    }
    
    func rotate(_ rcs: [Int], metrix: inout [[Int]]) {
        let row = rcs[0]-1
        let col = rcs[1]-1
        
        let origin = metrix
        
        for s in 1...rcs[2] {
            // 위
            for c in col-s..<col+s {
                metrix[row-s][c+1] = origin[row-s][c]
            }
            
            // 아래
            for c in (col-s+1...col+s).reversed() {
                metrix[row+s][c-1] = origin[row+s][c]
            }
            
            // 오른쪽
            for r in row-s..<row+s {
                metrix[r+1][col+s] = origin[r][col+s]
            }
            
            // 왼쪽
            for r in (row-s+1...row+s).reversed() {
                metrix[r-1][col-s] = origin[r][col-s]
            }
        }
    }
    
    func checkArray() {
        var copy = metrix
        for rcs in rcsList {
            rotate(rcs, metrix: &copy)
        }
        
        let arrayValue = copy.map({ $0.reduce(0, +) }).min()!
        
        if arrayValue < minResult {
            minResult = arrayValue
        }
    }
    
    func selectRcs(_ idx: Int) {
        guard idx < rcsList.count else {
            checkArray()
            return
        }
        
        for i in idx..<rcsList.count {
            rcsList.swapAt(i, idx)
            selectRcs(idx+1)
            rcsList.swapAt(i, idx)
        }
    }
    
    
    selectRcs(0)
    print(minResult)

     

    배운점

    갈 길이 멀다...

     

    'Algorithm > BOJ' 카테고리의 다른 글

    백준 12865 평범한 배낭  (0) 2021.03.30
    백준 2210 숫자판 점프  (0) 2021.03.29
    백준 16637 괄호 추가하기  (0) 2021.03.29
    백준 17471 게리맨더링  (0) 2021.03.28
    백준 17136 색종이 붙이기  (0) 2021.03.28

    댓글

Designed by Tistory.