문제
19235번: 모노미노도미노
모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,
www.acmicpc.net
알고리즘
구현, 시뮬레이션
풀이
20061. 모노미노도미노2 문제에서 조건이 하나 추가된 문제이다.
진한 색 보드에 가득 찬 줄이 있다면 블록을 지운 후 그 위에 있는 블록들을 지운 줄까지만 밀었지만
이번에는 그 위에 있는 블록들을 모두 맨 아래까지 떨어뜨리는 문제이다.
각 블록이 주어졌을 때 일어나는 과정은 다음과 같다.
1. 블록을 가능한 위치에 놓는다.
2. 가득찬 줄이 없을 때까지 터트린다. (여러 줄이라면 한번에)
3. 연한 색 보드에 블록이 남아있는 줄의 수만큼 맨 아래줄들을 삭제한다.
파란색 보드를 초록색 보드와 동일하게 사용하기 위해
파란색 보드의 순서일 경우 y,x를 바꾸고 t는 2<->3으로 바꿔주었다.
1. 블록 놓기
가능한 맨 아랫칸에 블록을 놓는다.
2번 블록은 좌우 칸이 둘 다 비어있어야 내릴 수 있다.
한 줄을 터트리고 난 후, 1과 3번 블록들은 가능한 맨 아래로 쭉 내리면 되지만
2번 블록의 경우 좌우 칸이 붙어있기 때문에, 아랫줄의 두 칸이 모두 비어있을 때만 내릴 수 있다.
따라서 다른 블록들과 다르게 표시를 해주어야하고,
또 2번 블록이 2개 이상 붙어있을 때 가운데 있는 블록은 왼쪽 블록과 붙어있는지 오른쪽 블록과 붙어있는지 구분해야하기 때문에
1, 3번 블록은 1로
2번 블록의 왼쪽 블록은 2로, 오른쪽 블록은 3으로 표시하였다.
2. 가득찬 줄이 없을 때까지 터트리기
터트릴 수 있는 줄이 있다면 해당 줄의 수를 세 score에 더해주고 해당 칸을 모두 0으로 변경한다.
모두 변경했다면 모든 블록을 가능한 맨 아래로 내리고
맨 아래로 내린 후에 터르릴 수 있는 줄이 또 생길 수 있기 때문에 터트릴 수 있는 줄이 없을 때까지 위 과정을 반복한다.
맨 아래로 내릴 때 배열에 1로 표시되어있는 1, 3번 블록의 경우 그대로 내리고,
2로 표시되어있는 2번 블록의 왼쪽 블록의 경우 아랫줄의 한 칸 오른쪽도 비어있을 때 내리면 두 칸을 모두 내린다.
3. 연한 색 보드에 블록이 남아있는 줄의 수만큼 맨 아래줄들을 삭제
연한 색 보드에 블록이 남아있는 줄의 수를 세고
남아있는 줄이 있다면 그 수만큼 맨 아랫줄들을 제거하고 위의 블럭들을 아래로 내린다.
위 과정이 모두 끝나면 누적된 점수와 남아있는 블록의 수를 출력한다.
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int score, board[][][];
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
board = new int[2][6][4];
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine(), " ");
int t = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int x = Integer.parseInt(st.nextToken());
for (int j = 0; j < 2; j++) {
push(t, y, x, j);
pop(j);
remove(j);
}
}
int count = 0;
for (int k = 0; k < 2; k++)
for (int i = 0; i < 6; i++)
for (int j = 0; j < 4; j++)
if (board[k][i][j] != 0) count++;
System.out.println(score);
System.out.println(count);
}
private static void remove(int type) {
int lightCount = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 4; j++) {
if (board[type][i][j] != 0) {
lightCount++;
break;
}
}
}
if (lightCount == 0) return;
for (int i = 0; i < 4; i++) {
for (int j = 5; j >= lightCount; j--) {
board[type][j][i] = board[type][j - lightCount][i];
board[type][j - lightCount][i] = 0;
}
}
}
private static void pop(int type) {
while (true) {
int count = 0;
label1: for (int i = 5; i >= 2; i--) {
for (int j = 0; j <= 3; j++) {
if (board[type][i][j] == 0)
continue label1;
}
count++;
for (int k = 0; k < 4; k++) {
board[type][i][k] = 0;
}
}
if (count == 0) break;
score += count;
push(type);
}
}
private static void push(int type) {
for (int i = 4; i >= 0; i--) {
for (int j = 0; j < 4; j++) {
if (board[type][i][j] == 1 && board[type][i + 1][j] == 0) {
int ny = i + 2;
while (ny <= 5 && board[type][ny][j] == 0) {
ny++;
}
board[type][ny - 1][j] = 1;
board[type][i][j] = 0;
} else if (board[type][i][j] == 2 && board[type][i + 1][j] == 0 && board[type][i + 1][j + 1] == 0) {
int ny = i + 2;
while (ny <= 5 && board[type][ny][j] == 0 && board[type][ny][j + 1] == 0) {
ny++;
}
board[type][ny - 1][j] = 2;
board[type][ny - 1][j + 1] = 3;
board[type][i][j] = 0;
board[type][i][j + 1] = 0;
}
}
}
}
static void push(int t, int y, int x, int type) {
if (type == 1) {
int tmp = x;
x = y;
y = tmp;
if (t == 2) t = 3;
else if (t == 3) t = 2;
}
if (t == 1) {
int ny = 1;
while (ny <= 5 && board[type][ny][x] == 0) ny++;
board[type][ny - 1][x] = 1;
}
else if (t == 2) {
int ny = 1;
while (ny <= 5 && board[type][ny][x] == 0 && board[type][ny][x + 1] == 0) ny++;
board[type][ny - 1][x] = 2;
board[type][ny - 1][x + 1] = 3;
}
else if (t == 3) {
int ny = 2;
while (ny <= 5 && board[type][ny][x] == 0) ny++;
board[type][ny - 1][x] = 1;
board[type][ny - 2][x] = 1;
}
}
}
'Algorithm > 백준(BOJ)' 카테고리의 다른 글
[백준] 1806. 부분합 (Java) (0) | 2022.10.10 |
---|---|
[백준] 1854. K번째 최단경로 찾기 (Java) (0) | 2022.10.10 |
[백준] 2458. 키 순서 (Java) (0) | 2022.10.07 |
[백준] 1948. 임계경로 (Java) (0) | 2022.10.07 |
[백준] 17472. 다리 만들기 2 (Java) (0) | 2022.10.07 |