in.add()

[84021] 3주차_퍼즐 조각 채우기 본문

Algorithm/Programmers

[84021] 3주차_퍼즐 조각 채우기

idan 2021. 10. 29. 23:10

문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/84021

 

코딩테스트 연습 - 3주차_퍼즐 조각 채우기

[[1,1,0,0,1,0],[0,0,1,0,1,0],[0,1,1,0,0,1],[1,1,0,1,1,1],[1,0,0,0,1,0],[0,1,1,1,0,0]] [[1,0,0,1,1,0],[1,0,1,0,1,0],[0,1,1,0,1,1],[0,0,1,0,0,0],[1,1,0,1,1,0],[0,1,0,0,0,0]] 14 [[0,0,0],[1,1,0],[1,1,1]] [[1,1,1],[1,0,0],[0,0,0]] 0

programmers.co.kr

 

문제 해결 방법

새로운 newBoard와 newTable을 만든다. 도형이 들어갈 칸은 그 크기의 수로 초기화한다(bfs 사용).

Table도 마찬가지로 초기화한다.

newBoard의 칸마다 보면서 0보다 크다면 newTable에서 같은 수를 가진 칸을 찾아 채울수있는지 확인하고, 채워 넣는다.

채워 넣을수 있다면 newBoard와 newTable의 숫자를 -1로 바꾼다.

 

같은과정을 newBoard를 90도씩 돌리며 4번 확인한다.

 

 

import java.util.*;

class Solution {
    static int L, answer;
    static int[][] newBoard;
    static int[][] newTable;
    static int[] dr = {1, 0, -1, 0};
    static int[] dc = {0, 1, 0, -1};
    public int solution(int[][] game_board, int[][] table) {
        answer = 0;
        L = game_board.length;
        newBoard = new int[L][L];
        newTable = new int[L][L];
        init(game_board, table); // 새로운 newBoard와 newTable을 만든다.
        
        for(int r = 0; r < 4; r++) { // newBoard를 90도씩 돌리며 4번 확인한다.
            for(int i = 0; i < L; i++) {
                for(int j = 0; j < L; j++) {
                    int n = newBoard[i][j]; // newBoard의 칸마다 보면서
                    if(n > 0) { // 0보다 크다면
                        for(int a = 0; a < L; a++) {
                            for(int b = 0; b < L; b++) {
                                if(n == newTable[a][b]) { // newTable에서 같은 수를 가진 칸을 찾아 채울수있는지 확인.
                                    fill(i, j, a, b);
                                }
                            }
                        }
                    }
                }
            }
            rotateBoard();
        }
        
        return answer;
    }
    
    public void init(int[][] game_board, int[][] table) { // 도형이 들어갈 칸은 그 크기의 수로 초기화한다.
        for(int i = 0; i < L; i++) {
            for(int j = 0; j < L; j++) {
                if(game_board[i][j] == 0) {
                    setNum(game_board, 0, i, j);
                } else newBoard[i][j] = -1;
                
                if(table[i][j] == 1) {
                    setNum(table, 1, i, j);
                } else newTable[i][j] = -1;
            }
        }
    }
    
    public void setNum(int[][] map, int boardOrTable, int r, int c) {
        boolean[][] visit = new boolean[L][L];
        Queue<int[]> q = new LinkedList<>();
        Queue<int[]> tmpQ = new LinkedList<>();
        q.add(new int[]{r, c});
        visit[r][c] = true;
        
        while(!q.isEmpty()) {
            int[] cur = q.poll();
            tmpQ.add(cur);
            
            for(int i = 0; i < 4; i++) {
                int nextR = cur[0] + dr[i];
                int nextC = cur[1] + dc[i];
                
                if(nextR < 0 || nextC < 0 || nextR >= L || nextC >= L || visit[nextR][nextC]) continue;
                if(boardOrTable == 0 && map[nextR][nextC] != 0) continue;
                else if(boardOrTable == 1 && map[nextR][nextC] != 1) continue;
                
                q.add(new int[]{nextR, nextC});
                visit[nextR][nextC] = true;
            }
        }
        
        int num = tmpQ.size();
        while(!tmpQ.isEmpty()) {
            int[] cur = tmpQ.poll();
            if(boardOrTable == 0) newBoard[cur[0]][cur[1]] = num;
            else if(boardOrTable == 1) newTable[cur[0]][cur[1]] = num;
        }
    }

    public void rotateBoard() {
        int[][] copy = new int[L][L];

        for (int i = 0; i < L; i++) {
            for (int j = 0; j < L; j++) {
                copy[i][j] = newBoard[L - 1 - j][i];
            }
        }

        for (int i = 0; i < L; i++) {
            newBoard[i] = copy[i].clone();
        }
    }
    
    public void fill(int r, int c, int a, int b) { // bfs로 채워 넣을수 있는지 확인.
        int num = newBoard[r][c];
        boolean[][] visitB = new boolean[L][L];
        Queue<int[]> q = new LinkedList<>();
        Queue<int[]> tmpQ = new LinkedList<>();
        q.add(new int[]{r, c, a, b});
        visitB[r][c] = true;
        
        while(!q.isEmpty()) {
            int[] cur = q.poll();
            tmpQ.add(cur);
            
            for(int i = 0; i < 4; i++) {
                int nextRB = cur[0] + dr[i];
                int nextCB = cur[1] + dc[i];
                int nextRT = cur[2] + dr[i];
                int nextCT = cur[3] + dc[i];

                if(nextRB < 0 || nextCB < 0 || nextRB >= L || nextCB >= L || visitB[nextRB][nextCB]) continue;
                if(nextRT < 0 || nextCT < 0 || nextRT >= L || nextCT >= L) continue;
                if(newBoard[nextRB][nextCB] != num) continue;
                if(newTable[nextRT][nextCT] != num) continue;
                
                q.add(new int[]{nextRB, nextCB, nextRT, nextCT});
                visitB[nextRB][nextCB] = true;
            }
        }
        
        if(num != tmpQ.size()) return; // num과 tmpQ의 크기가 같아야 채워 넣을수 있다.
        
        answer += num;
        while(!tmpQ.isEmpty()) { // 채워 넣을수 있다면 newBoard와 newTable의 숫자를 -1로 바꾼다.
            int[] cur = tmpQ.poll();
            newBoard[cur[0]][cur[1]] = -1;
            newTable[cur[2]][cur[3]] = -1;
        }
    }
}

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

[42579] 베스트 앨범  (0) 2021.11.08
[42628] 이중우선순위큐  (0) 2021.10.28
[43162] 네트워크  (0) 2021.10.26
[62048] 멀쩡한 사각형  (0) 2021.10.25
[1844] 게임 맵 최단거리  (0) 2021.10.16
Comments