[백준][JAVA] BOJ 20061 모노미노도미노2

2023. 5. 1. 19:42· 코딩테스트준비/백준
목차
  1. 문제 읽기🤔
  2. 문제 풀이📝
  3. 구현🛠️
  4. 실행결과✅
반응형

문제 읽기🤔


문제가 너무 길어서 요약으로 대체합니다 :)

위와 같이 모노미노도미노 게임을 위한 보드가 주어진다.

모노미노도미노 게임에서 사용되는 블록은 다음과 같다.

빨간 보드에 블럭을 놓으면 해당 위치 기준으로 더 이상 움직일 수 없을 때까지 행/열을 따라 이동한다.

 

블럭이 사라지는 경우

1) (초록)행//(파랑)열이 모두 블럭으로 채워진 경우

  -> 해당 줄의 블럭은 모두 사라짐, 해당 줄의 앞줄에 존재하는 블럭들은 사라진 행/열의 개수만큼 행/열을 따라 뒤로 이동

  -> 1점을 얻는다.

2) 희미한 부분에 블럭이 채워진 경우

  -> 희미한 부분에 블럭이 있는 (초록)행/(파랑)열의 수만큼 맨 뒷 행/열에 있는 타일들이 사라짐

  -> 해당 줄의 앞줄에 존재하는 블럭들은 사라진 행/열의 개수만큼 행/열을 따라 뒤로 이동

1, 2번 경우가 모두 발생하는 경우에는 1을 실행한 후 2를 실행한다.

 

얻은 총 점수와 초록색 보드, 파란색 보드에 타일이 있는 칸의 개수를 출력하라.

 

 

문제 풀이📝


꼼꼼하게 구현만 잘하면 되는 시뮬레이션 문제였다.

 

1. 빨간색 보드에 놓은 블럭을 파란색 보드, 초록색 보드로 이동시킨다.

2. (초록)행/(파랑)열이 블럭으로 모두 채워졌는지 검사한다.

  -> 채워진 행/열이 존재한다면 해당 행/열의 타일들을 지우고, 앞쪽의 타일들을 이동시킨다.

  -> 총 점수에 1점을 더해준다.

3. 희미한 부분에 블럭이 있는 경우를 검사한다.

  -> 희미한 부분에 블럭이 있는 (초록)행/(파랑)열의 개수만큼 맨 뒤부터 한 줄씩 타일을 지우고, 앞쪽의 타일들을 이동시킨다.

 

함수를 잘 재사용하여 깔끔한 코드를 짜고 싶었지만,,, 쉽지가 않았다.

다음에 기회가 된다면 꼭 리팩토링 하고 싶다.

 

 

구현🛠️


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

// 초록색 보드와 파란색 보드의 위치를 헷갈렸습니다^^,,,
// 반대로 생각하고 읽으시면 됩니다.
public class Main {

    static final int MAX = 6;
    static final int GREEN = 0;
    static final int BLUE = 1;

    // 우, 상
    static final int[] DR = {0, 1};
    static final int[] DC = {1, 0};

    static int[][] greenBoard;
    static int[][] blueBoard;

    static int score;


    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        greenBoard = new int[MAX - 2][MAX];
        blueBoard = new int[MAX][MAX - 2];

        int N = Integer.parseInt(br.readLine());
        for (int i = 0; i < N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int type = Integer.parseInt(st.nextToken());
            int row = Integer.parseInt(st.nextToken());
            int col = Integer.parseInt(st.nextToken());
            put(type, row, col);
        }
        System.out.println(score);
        System.out.println(getRemainingTiles());
    }

    static void put(int type, int row, int col) {


        switch (type) {
            // 1x1
            case 1:
                drop(new int[]{row, 0}, new int[]{row, 0}, GREEN);
                drop(new int[]{0, col}, new int[]{0, col}, BLUE);
                break;
            // 1x2
            case 2:
                drop(new int[]{row, 0}, new int[]{row, 1}, GREEN);
                drop(new int[]{0, col}, new int[]{0, col + 1}, BLUE);
                break;
            // 2x1
            case 3:
                drop(new int[]{row, 0}, new int[]{row + 1, 0}, GREEN);
                drop(new int[]{0, col}, new int[]{1, col}, BLUE);
                break;
        }

        // 한 행/열이 꽉 찼는지 확인
        checkLine();
        // 희미한 구역 확인
        checkFaintArea();
    }

    static void drop(int[] start, int[] end, int color) {

        int[][] board = (color == GREEN ? greenBoard : blueBoard);
        int[] nStart = {start[0], start[1]};
        int[] nEnd = {end[0], end[1]};

        while (true) {
            int nx1 = nStart[0] + DR[color];
            int ny1 = nStart[1] + DC[color];
            int nx2 = nEnd[0] + DR[color];
            int ny2 = nEnd[1] + DC[color];
            // 끝에 도달
            if (isOutOfBound(nx1, ny1) || isOutOfBound(nx2, ny2)) {
                break;
            }
            // 다른 블럭과 충돌
            if (board[nx1][ny1] != 0 || board[nx2][ny2] != 0) {
                break;
            }
            nStart[0] = nx1;
            nStart[1] = ny1;
            nEnd[0] = nx2;
            nEnd[1] = ny2;
        }
        board[nStart[0]][nStart[1]] = 1;
        board[nEnd[0]][nEnd[1]] = 1;
    }

    static boolean isOutOfBound(int r, int c) {
        if (r >= MAX || c >= MAX) {
            return true;
        }
        return false;
    }

    static void checkLine(){

        int greenCount = 0;
        int greenIdx = -1;

        int blueCount = 0;
        int blueIdx = -1;

        for (int i = MAX - 1; i >= 2; i--) {

            int gCount = 0;
            int bCount = 0;
            for (int j = 0; j < 4; j++) {
                if (greenBoard[j][i] != 0) {
                    gCount++;
                }
                if (blueBoard[i][j] != 0) {
                    bCount++;
                }
            }
            // 한 줄이 꽉 채워진 경우
            if (gCount == 4){
                greenCount++;
                greenIdx = i;
                pop(greenIdx, GREEN);
            }

            if (bCount == 4){
                blueCount++;
                blueIdx = i;
                pop(blueIdx, BLUE);
            }
        }

        // 한 줄 이상이 채워져서 사라진 경우에만 -> 앞쪽의 블럭들을 (지운 줄의 개수)칸 만큼 옮긴다
        if (greenIdx != -1){
            pull(greenCount, greenIdx - 1, GREEN);
        }

        if (blueIdx != -1){
            pull(blueCount, blueIdx - 1, BLUE);
        }

        score = score + greenCount + blueCount;
    }

    static void checkFaintArea() {

        int greenCount = 0;
        int blueCount = 0;

        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 4; j++) {
                if (greenBoard[j][i] != 0) {
                    greenCount++;
                    break;
                }
            }
        }
        // 맨 뒤부터 한 줄씩 지워나간다
        for (int i = 0; i < greenCount; i++) {
            pop((MAX - i) - 1, GREEN);
        }
        // 지운 줄의 앞쪽의 블럭들을 (지운 줄의 개수)칸 만큼 옮긴다
        pull(greenCount, (MAX - greenCount) - 1, GREEN);

        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 4; j++) {
                if (blueBoard[i][j] != 0) {
                    blueCount++;
                    break;
                }
            }
        }
        for (int i = 0; i < blueCount; i++) {
            pop((MAX - i) - 1, BLUE);
        }
        pull(blueCount, (MAX - blueCount) - 1, BLUE);
    }

    static void pop(int idx, int color){

        for (int i = 0; i < 4; i++) {
            if (color == GREEN){
                greenBoard[i][idx] = 0;
            }
            if (color == BLUE){
                blueBoard[idx][i] = 0;
            }
        }
    }

    static void pull(int count, int idx, int color) {

        for (int i = 0; i < 4; i++) {

            for (int j = idx; j >= 0; j--) {

                if (color == GREEN){
                    if (greenBoard[i][j] != 0){
                        greenBoard[i][j] = 0;
                        greenBoard[i + DR[color] * count][j + DC[color] * count] = 1;
                    }
                }

                if (color == BLUE){
                    if (blueBoard[j][i] != 0){
                        blueBoard[j][i] = 0;
                        blueBoard[j + DR[color] * count][i + DC[color] * count] = 1;
                    }
                }
            }
        }
    }

    static int getRemainingTiles() {

        int total = 0;

        for (int i = 0; i < MAX - 2; i++) {

            for (int j = 2; j < MAX; j++) {

                if (greenBoard[i][j] != 0) {
                    total++;
                }
                if (blueBoard[j][i] != 0) {
                    total++;
                }
            }
        }
        return total;
    }
}

 

 

실행결과✅


'코딩테스트준비 > 백준' 카테고리의 다른 글

[백준][JAVA] BOJ 14725 개미굴  (0) 2023.05.31
[백준][JAVA] BOJ 20188 등산 마니아  (2) 2023.05.03
[백준][JAVA] BOJ 2138 전구와 스위치  (0) 2023.05.01
[백준][JAVA] BOJ 16954 움직이는 미로 탈출  (1) 2023.05.01
[백준][JAVA] BOJ 14890 경사로  (0) 2023.02.22
  1. 문제 읽기🤔
  2. 문제 풀이📝
  3. 구현🛠️
  4. 실행결과✅
'코딩테스트준비/백준' 카테고리의 다른 글
  • [백준][JAVA] BOJ 14725 개미굴
  • [백준][JAVA] BOJ 20188 등산 마니아
  • [백준][JAVA] BOJ 2138 전구와 스위치
  • [백준][JAVA] BOJ 16954 움직이는 미로 탈출
소윤파크
소윤파크
아는 만큼 보인다.
소윤파크
쏘's 코드
소윤파크
전체
오늘
어제
  • 분류 전체보기 (27)
    • Spring (2)
      • Annotation (1)
      • JUnit (0)
      • JPA (0)
    • IDE (0)
    • Java (0)
    • 도전 (3)
    • 알고리즘 (1)
    • 코딩테스트준비 (15)
      • 백준 (13)
      • 프로그래머스 (2)
    • 잡학다식 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 트리에서의 DP
  • 백준
  • 코딩테스트
  • Java
  • 오공완
  • Prim 알고리즘
  • 물대기
  • 최종 순위
  • BOJ1931
  • 코테
  • BOJ14890
  • 우아한테크코스
  • BOJ 3665
  • 트라이 알고리즘
  • 프로그래머스
  • 시뮬레이션
  • 골드
  • 전구와 스위치
  • 3진법뒤집기
  • 그리디
  • 모노미노도미노2
  • 우테코
  • 등산마니아
  • 구현
  • BOJ14725
  • 2018 KAKAO RECRUITMENT
  • 삼성청년SW아카데미
  • 움직이는 미로 탈출
  • BOJ 1368
  • 알고리즘

최근 댓글

hELLO · Designed By 정상우.v4.2.2
소윤파크
[백준][JAVA] BOJ 20061 모노미노도미노2
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.