티스토리 뷰
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를 집어넣는다.
'Problem Solving' 카테고리의 다른 글
[BOJ 17144] 미세먼지 안녕! (Java) (0) | 2022.04.23 |
---|---|
[BOJ 23288] 주사위 굴리기 2 (Java) (0) | 2022.04.21 |
[BOJ 21610] 마법사 상어와 비바라기 (Java) (0) | 2022.04.19 |
[BOJ 1520] 내리막 길 (Java) (0) | 2022.04.18 |
[BOJ 1005] ACM Craft (Java) (0) | 2022.04.15 |