Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

Life Engineering

[BOJ 20061] 모노미노도미노2 (Java) 본문

Problem Solving

[BOJ 20061] 모노미노도미노2 (Java)

흑개 2022. 4. 21. 01:11

https://www.acmicpc.net/problem/20061

 

20061번: 모노미노도미노 2

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

www.acmicpc.net

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

public class Main_BOJ_20061 {
	static int N, cnt=0;
	static boolean[][] board=new boolean[10][10];
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st=null;
		N=Integer.parseInt(br.readLine());
		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());
			arrange(t, x, y);
			/*
			for (int a=0; a<10; a++) {
				System.out.println(Arrays.toString(board[a]));
			} 
			*/
			while (true) {
				if (!isFull()) break;
			}
			faded();
		}
		System.out.println(cnt);
		int blocks=0;
		for (int i=0; i<4; i++) {
			for (int j=4; j<10; j++) {
				if (board[i][j]) blocks++;
			}
		}
		for (int i=4; i<10; i++) {
			for (int j=0; j<4; j++) {
				if (board[i][j]) blocks++;
			}
		}
		System.out.println(blocks);

	}
	private static void faded() {
		int line=0;				//blue
		for (int i=4; i<=5; i++) {
			for (int j=0; j<4; j++) {
				if (board[j][i]==true) {
					line++;
					break;
				}
			}
		}
		if (line>0) {
			int last=9;
			for (int i=9-line; i>=4; i--) {
				for (int j=0; j<4; j++) {
					board[j][last]=board[j][i];
				}
				last--;
			}
			for (int i=4; i<4+line; i++) {
				for (int j=0; j<4; j++) {
					board[j][i]=false;
				}
			}
		}
		line=0;				//green
		for (int i=4; i<=5; i++) {
			for (int j=0; j<4; j++) {
				if (board[i][j]==true) {
					line++;
					break;
				}
			}
		}
		if (line>0) {
			int last=9;
			for (int i=9-line; i>=4; i--) {
				for (int j=0; j<4; j++) {
					board[last][j]=board[i][j];
				}
				last--;
			}
			for (int i=4; i<4+line; i++) {
				for (int j=0; j<4; j++) {
					board[i][j]=false;
				}
			}
		}	
	}
		
	private static boolean isFull() {
		boolean flag=false;
		int last=5;
		boolean[][] temp=new boolean[4][6];
		for (int i=9; i>=4; i--) {
			boolean full=true;
			for (int j=0; j<4; j++) {
				if (!board[j][i]) {
					full=false;
					break;
				}
			}
			if (full) {		//가득 찬 경우
				cnt++;
				flag=true;
			}
			else {
				for (int j=0; j<4; j++) {
					temp[j][last]=board[j][i];
				}
				last--;
			}
		}
		for (int i=0; i<4; i++) {
			for (int j=4; j<10; j++) {
				board[i][j]=temp[i][j-4];
			}
		}
		last=5;
		temp=new boolean[6][4];
		for (int i=9; i>=4; i--) {
			boolean full=true;
			for (int j=0; j<4; j++) {
				if (!board[i][j]) {
					full=false;
					break;
				}
			}
			if (full) {		//가득 찬 경우
				cnt++;
				flag=true;
			}
			else {
				for (int j=0; j<4; j++) {
					temp[last][j]=board[i][j];
				}
				last--;
			}
		}
		for (int i=4; i<10; i++) {
			for (int j=0; j<4; j++) {
				board[i][j]=temp[i-4][j];
			}
		}
		return flag;
	}
	private static void arrange(int t, int x, int y) {
		blocksMove(x,y,t,1);
		blocksMove(x,y,t,2);	
	}
	private static void blocksMove(int x, int y, int t, int color) {
		int nx=x, ny=y;
		while (true) {
			if (t==1 && isImpossible(nx, ny)) {
				break;
			}
			else if (t==2 && (isImpossible(nx, ny) || isImpossible(nx, ny+1))) {
				break;
			}
			else if (t==3 && (isImpossible(nx, ny) || isImpossible(nx+1, ny))) {
				break;
			}
			if (color==1) ny+=1;
			else nx+=1;
		}
		if (color==1) ny-=1;
		else nx-=1;
		if (t==1) board[nx][ny]=true;
		else if (t==2) {
			board[nx][ny]=true;
			board[nx][ny+1]=true;
		}
		else {
			board[nx][ny]=true;
			board[nx+1][ny]=true;
		}
	}
	private static boolean isImpossible(int nx, int ny) {
		if (nx<0 || ny<0 || nx>=10 || ny>=10) return true;
		if (board[nx][ny]) return true;
		return false;
	}


}

구현 및 시뮬레이션 문제

 

문제의 조건을 보고 정확하게 구현하는 것이 포인트다.

 

board[i][j] => true이면 해당 칸에 블록이 있음, false이면 빈칸 

 

1) arrange 함수, blocksMove 함수: 블록을 움직이는 함수이다. 각 블록의 타입에 따라서 가능한 만큼 움직여준다.

파란색 영역으로 움직일 경우 오른쪽으로 +1(ny+=1) 해서 움직여주고, 초록색 영역으로 움직일 경우에 아래쪽으로 +1(nx+=1) 해서 움직여준다. 이때 가능한 경우는 isImpossible 함수로 검사하는데, 해당 영역이 다른 블록에 속하거나 아니면 영역 밖일 경우 true를 리턴한다.

 

2) isFull 함수: 블록으로 가득찬 행/열을 고르고 이에 따라 움직이는 함수이다. 블록으로 가득찬 행/열이 없을 때까지 반복된다. 가득찬 행/열의 갯수를 세주고, temp 배열에 가득차지 않은 행/열을 넣어준다.

이후 board 배열에 temp 배열을 대입하여 움직임을 업데이트 해준다. 

 

3)faded 함수: 0,1번째 행/열에 대해 블록이 있으면 이를 조건에 따라 움직이는 함수이다. 

블록이 있는 행/열의 갯수를 세어주고, 이 갯수에 맞게 board의 값들을 파란색 영역의 경우 오른쪽으로 line 칸 밀어주고, 초록색 영역의 경우 아래쪽으로 line 칸 밀어준다. 그리고 밀어준 뒤 앞쪽에 빈칸이 생기게 되는데, 이것을 line 갯수만큼 돌아주면서 board에 false를 집어넣는다.