본문 바로가기
백준

[백준] code.plus(시뮬레이션과 구현,JAVA)20061번, 도노미노도미노 2

by 열정적인 이찬형 2022. 8. 13.

문제 링크

 

20061번: 모노미노도미노 2

모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,

www.acmicpc.net


주의사항

  • JAVA를 사용하여 프로그램을 사용하였습니다.
  • 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{ 	
	public static void main(String[] args){
    }
}

문제 설명

문제 내용이 많아서 핵심적인 부분만 보여드리고 전체는 링크를 들어가셔서 확인해주시면 감사하겠습니다.


접근 방법

 

이 문제에 핵심은

 

1. 3가지 모양의 도형이 오른쪽, 아래쪽 방향으로 이동하면서 채워간다.

2. 행이나 열이 완성되면 없어지고 한 칸씩 땡겨진다.

3. 연한색 구간에 도형이 있을 경우 그 열이나 행 개수만큼 가장 아래 구간을 제거 및 땡겨집니다.

4. 모든 도형의 이동이 이루어진 뒤에 모형이 존재하는 칸의 개수를 결과로 출력합니다.

 

알고리즘 진행 순서.

 

1. 입력되는 정보들을 저장합니다.

 

2. 문제에서 설명한 내용을 그대로 시뮬레이션을 진행하였습니다.

 

3. 모든 도형에 시뮬레이션 종료 후 존재하는 칸의 개수를 결과로 출력합니다.

 

 

 

예제입력 1~7까지 진행과정을 문제에서 그림으로 보여주고 있습니다.

 

  • BufferedReader를 사용하여 입력 값을 받았습니다.
  • StringTokenizer를 이용하여 입력된 정보에 대하여 나누었습니다.
  • blueMove, greenMove 실행하여 시뮬레이션을 진행합니다.
  • 시뮬레이션 종료 후 점수와 getMap을 통해 도형이 남은 칸의 개수를 BufferedWriter 저장하였습니다.
  • BufferedWriter에 저장된 결과값을 출력하였습니다.
  • blueMove,greenMove함수는 blueComplete, lightBlueCheck.... 을 이용하여 시뮬레이션을 진행합니다.
  • blueComplete, greenComplete함수는 도형 이동 후 도형에 따라 행이나 열이 완성되는 것을 확인, 변경하는 함수들을 호출합니다.
  • blueValueMove, greenValueMove함수는 값들을 땡기는 역활을 수행합니다.
  • blueColCheck, greenRowCheck함수는 각 행이나 열이 완성되었는지 확인합니다.
  • lightBlueCheck, lightGreenCheck함수는 연한 부분에 도형이 존재하는 칸이 있는지 확인합니다.
  • getMap함수는 시뮬레이션 종료 후 초록색, 파란색에 남아있는 도형이 있는 칸의 개수를 구합니다.

 

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    static int N, point = 0;
    static int[][] green = new int[6][4];	//초록색 구역
    static int[][] blue = new int[4][6];	//파란색 구역
    public static void main(String[] args) throws IOException {
        //입력값 처리하는 BufferedReader
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //결과값 출력하는 BufferedWriter
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        N = Integer.parseInt(br.readLine());
        StringTokenizer st;
        //도형 정보 저장 및 시뮬레이션 진행
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine(), " ");
            int t = Integer.parseInt(st.nextToken());
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());
            blueMove(t, x);	//도형 파란색 칸으로 이동
            greenMove(t, y);	//도형 초록색 칸으로 이동
        }
        bw.write( point + "\n" + getMap());	// 결과 BufferedWriter 저장
        bw.flush();		//결과 출력
        bw.close();
        br.close();
    }
    //도형 → 파란색 방향으로 이동
    static void blueMove(int t,  int x){
        int col = 5;
        if(t==1){
            for(int i=2;i<7;i++){
                if(i==6){
                    blue[x][5] = 1;
                    break;
                }
                if(blue[x][i] == 1){
                    blue[x][i-1] = 1;
                    col = i-1;
                    break;
                }
            }
        }else if(t==2){
            for(int i=2;i<7;i++){
                if(i==6){
                    blue[x][5] = 1;
                    blue[x][4] = 1;
                    break;
                }
                if(blue[x][i] == 1){
                    blue[x][i-1] = 1;
                    blue[x][i-2] = 1;
                    col = i-1;
                    break;
                }
            }
        }else{
            for(int i=2;i<7;i++){
                if(i==6){
                    blue[x][5] = 1;
                    blue[x+1][5] = 1;
                    break;
                }
                if(blue[x][i] == 1 || blue[x+1][i]==1){
                    blue[x][i-1] = 1;
                    blue[x+1][i-1] = 1;
                    col = i-1;
                    break;
                }
            }
        }
        blueComplete(t, col);	//이동 후 완성된 열이 있는지 확인
        //연한 부분 탐색
        int minus = lightBlueCheck(1) + lightBlueCheck(0);
        if(minus!=0)	//연한 부분에 도형 존재시 해당 칸만큼 땡기기
            blueValueMove(minus, 5);
    }
    //연한 부분 탐색하는 함수
    static int lightBlueCheck(int col){
        for(int i=0;i<4;i++)
            if(blue[i][col]==1)	//도형 존재시.
                return 1;
        return 0;
    }
    //도형 파란색 부분 이동 후 열 확인하는 함수
    static void blueComplete(int t, int col){
        if(t==1 || t==3){
            if(blueColCheck(col) == 0)
                return;
            blueValueMove(1, col);
            point++;
        }else{
            int t1 = blueColCheck(col);
            int t2 = blueColCheck(col-1);
            if (t1 + t2==0)
                return;
            if(t1==0 && t2 == 1)
                blueValueMove(1, col-1);
            else
                blueValueMove(t1 + t2, col);
            point+=t1 + t2;
        }
    }
    //연한 파란색에 도형이 있거나 열이 완성된 경우 땡겨지는 것 진행하는 함수
    static void blueValueMove(int minus, int col){
        for(int i=col;i >= minus; i--) {
            for (int j = 0; j < 4; j++)
                blue[j][i] = blue[j][i - minus];
        }
        blue[0][0] = blue[1][0] = blue[2][0] = blue[3][0] = 0;
        if(minus==2)
            blue[0][1] = blue[1][1] = blue[2][1] = blue[3][1] = 0;
    }
    //해당 열의 칸에 모두 도형이 존재하는지 확인하는 함수
    static int blueColCheck(int col){
        for(int i=0;i<4;i++)
            if(blue[i][col]==0)
                return 0;
        return 1;
    }
    //도형 ↓ 초록색 방향으로 이동
    static void greenMove(int t, int y){
        int row = 5;
        if(t==1){
            for(int i=2;i<7;i++){
                if(i==6){
                    green[5][y] = 1;
                    break;
                }
                if(green[i][y] == 1){
                    green[i-1][y] = 1;
                    row = i-1;
                    break;
                }
            }
        }else if(t==2){
            for(int i=2;i<7;i++){
                if(i==6){
                    green[5][y] = 1;
                    green[5][y+1] = 1;
                    break;
                }
                if(green[i][y] == 1 || green[i][y+1]==1){
                    green[i-1][y] = 1;
                    green[i-1][y+1] = 1;
                    row = i-1;
                    break;
                }
            }
        }else{
            for(int i=2;i<7;i++){
                if(i==6){
                    green[4][y] = 1;
                    green[5][y] = 1;
                    break;
                }
                if(green[i][y] == 1){
                    green[i-1][y] = 1;
                    green[i-2][y] = 1;
                    row = i-1;
                    break;
                }
            }
        }
        greenComplete(t, row);	////이동 후 완성된 행이 있는지 확인
        //연한 부분 탐색
        int minus = lightGreenCheck(1) + lightGreenCheck(0);
        if(minus!=0)	//연한 부분에 도형 존재시 해당 칸만큼 땡기기
            greenValueMove(minus, 5);
    }
    //연한 부분 탐색하는 함수
    static int lightGreenCheck(int row){
        for(int i=0;i<4;i++)
            if(green[row][i]==1)
                return 1;
        return 0;
    }
    //도형 초록색 부분 이동 후 행 확인하는 함수
    static void greenComplete(int t, int row){
        if(t==1 || t==2){
            if(greenRowCheck(row) == 0)
                return;
            greenValueMove(1, row);
            point++;
        }else{
            int t1 = greenRowCheck(row);
            int t2 = greenRowCheck(row-1);
            if (t1 + t2==0)
                return;
            if(t1==0 && t2 == 1)
                greenValueMove(1, row-1);
            else
                greenValueMove(t1 + t2, row);
            point += t1 + t2;
        }
    }
    //연한 초록색에 도형이 있거나 행이 완성된 경우 땡겨지는 것 진행하는 함수
    static void greenValueMove(int minus, int row){
        for(int i=row;i >=minus; i--) {
            for (int j = 0; j < 4; j++)
                green[i][j] = green[i-minus][j];
        }
        green[0][0] = green[0][1] = green[0][2] = green[0][3] = 0;
        if(minus==2)
            green[1][0] = green[1][1] = green[1][2] = green[1][3] = 0;
    }
    //해당 행의 칸에 모두 도형이 존재하는지 확인하는 함수
    static int greenRowCheck(int row){
        for(int i=0;i<4;i++)
            if(green[row][i]==0)
                return 0;
        return 1;
    }
    //파란색, 초록색 부분에 도형이 남아있는 칸의 개수를 구하는 함수
    static int getMap(){
        int result = 0;
        for(int i=0;i<4;i++){
            for(int j=0;j<6;j++)
                result += blue[i][j];
        }
        for(int i=0;i<6;i++){
            for(int j=0;j<4;j++)
                result += green[i][j];
        }
        return result;
    }
}

댓글