본문 바로가기
Problem Solving/삼성 SW 역량 테스트 기출

백준 20061 : 모노미노도미노 2

by Libi 2021. 8. 3.
반응형

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

 

20061번: 모노미노도미노 2

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

www.acmicpc.net

[ 문제풀이 ]

단순 노가다 빡구현 문제이다. 주어진 조건에 맞게 블록들을 시뮬레이션 시켜주면 된다.

빡구현 문제는 설계를 잘해도 실수 한 번만하면 디버깅하는데 정말 힘든 것 같다. move 배열을 이용하여 블록들을 이동시켰는데 연한 영역 부분을 빠뜨리는 바람에 굉장히 힘들었다.

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

public class Main {

	static int score;
	static int[][] map;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		int N = Integer.parseInt(br.readLine());
		map = new int[10][10];
		while (N-- > 0) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int t = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());
			int x = Integer.parseInt(st.nextToken());

			//블록을 blue, green 영역으로 이동
			moveTheBlock(t, y, x);
			//blue, green 영역에 4칸이 찬 행/열을 제거하고 나머지 블록들을 이동시킨 후 점수를 증가
			getScore();
			//연한 영역에 블록이 존재한다면 존재하는 행/열의 수만큼 블록들을 이동
			isCheck();
		}

		bw.write(score + "\n" + blockCnt() + "\n");
		bw.flush();bw.close();br.close();
	}

	public static void moveTheBlock(int t, int y, int x) {
		if (t == 1) {
			//Blue 영역
			for (int i = x; i <= 8; ++i) {
				if (map[y][i + 1] == 1) {
					map[y][i] = 1;
					break;
				} else {
					//마지막 라인에 블록이 존재하지 않으면 블록 삽입
					if (i == 8) {
						map[y][i + 1] = 1;
					}
				}
			}
			//Green 영역
			for (int i = y; i <= 8; ++i) {
				if (map[i + 1][x] == 1) {
					map[i][x] = 1;
					break;
				} else {
					//마지막 라인에 블록이 존재하지 않으면 블록 삽입
					if (i == 8) {
						map[i + 1][x] = 1;
					}
				}
			}
		} else if (t == 2) {
			//Blue 영역
			for (int i = x; i <= 7; ++i) {
				if (map[y][i + 2] == 1) {
					map[y][i] = 1; map[y][i + 1] = 1;
					break;
				} else {
					//마지막 라인에 블록이 존재하지 않으면 블록 삽입
					if (i == 7) {
						map[y][i + 2] = 1; map[y][i + 1] = 1;
					}
				}
			}
			//Green 영역
			for (int i = y; i <= 8; ++i) {
				if (map[i + 1][x] == 1 || map[i + 1][x + 1] == 1) {
					map[i][x] = 1; map[i][x + 1] = 1;
					break;
				} else {
					//마지막 라인에 블록이 존재하지 않으면 블록 삽입
					if (i == 8) {
						map[i + 1][x] = 1; map[i + 1][x + 1] = 1;
					}
				}
			}
		} else if (t == 3) {
			//Blue 영역
			for (int i = x; i <= 8; ++i) {
				if (map[y][i + 1] == 1 || map[y + 1][i + 1] == 1) {
					map[y][i] = 1; map[y + 1][i] = 1;
					break;
				} else {
					//마지막 라인에 블록이 존재하지 않으면 블록 삽입
					if (i == 8) {
						map[y][i + 1] = 1; map[y + 1][i + 1] = 1;
					}
				}
			}
			//Green 영역
			for (int i = y; i <= 7; ++i) {
				if (map[i + 2][x] == 1) {
					map[i][x] = 1; map[i + 1][x] = 1;
					break;
				} else {
					//마지막 라인에 블록이 존재하지 않으면 블록 삽입
					if (i == 7) {
						map[i + 1][x] = 1; map[i + 2][x] = 1;
					}
				}
			}
		}
	}

	public static void getScore() {
		int[] move = new int[11]; //move[i] = i(행/열)의 블록이 내려가야하는 이동횟수

		//Green 영역
		boolean	flag = false;

		for (int i = 9; i >= 6; --i) {
			int cnt = 0;

			for (int j = 0; j < 4; ++j) {
				if (map[i][j] == 1) cnt++;
				else break;
			}

			move[i] = move[i + 1];

			//만약 i번째 행의 블록이 꽉찼다면
			if (cnt == 4) {
				flag = true;
				score++;
				move[i]++; //i행 위로의 블록은 1칸 내려줘야함

				for (int j = 0; j < 4; ++j) {
					map[i][j] = 0;
				}
			}
		}

		move[4] = move[5] = move[6]; //연한 영역은 따로 이동횟수를 저장해줌

		if (flag) {
			for (int i = 8; i >= 4; --i) {
				if (move[i] == 0) continue;
				for (int j = 0; j < 4; ++j) {
					//i행에 블록이 존재하면 i+move[i]행만큼 이동
					if (map[i][j] == 1) {
						map[i + move[i]][j] = 1;
						map[i][j] = 0;
					}
				}
			}
		}

		Arrays.fill(move, 0);

		//Blue 영역
		flag = false;
		
		for (int j = 9; j >= 6; --j) {
			int cnt = 0;
			for (int i = 0; i < 4; ++i) {
				if (map[i][j] == 1) cnt++;
				else break;
			}
			move[j] = move[j + 1];

			//만약 j번째 열의 블록이 꽉찼다면
			if (cnt == 4) {
				flag = true;
				score++;
				move[j]++; //j열 위로의 블록은 1칸 내려줘야함

				for (int i = 0; i < 4; ++i) {
					map[i][j] = 0;
				}
			}
		}

		move[4] = move[5] = move[6]; //연한 영역은 따로 이동횟수를 저장해줌

		if (flag) {
			for (int j = 8; j >= 4; --j) {
				if (move[j] == 0) continue;
				for (int i = 0; i < 4; ++i) {
					//j열에 블록이 존재하면 j+move[j]열만큼 이동
					if (map[i][j] == 1) {
						map[i][j + move[j]] = 1;
						map[i][j] = 0;
					}
				}
			}
		}
	}

	public static void isCheck() {
		int cnt = 0;

		//연한 green 영영에 블록이 있는 행의 수를 구함
		for (int i = 4; i <= 5; ++i) {
			for (int j = 0; j < 4; ++j) {
				if (map[i][j] == 1) {
					cnt++;
					break;
				}
			}
		}

		if (cnt > 0) {
			for (int i = 9; i >= 4; --i) {
				// 구한 행의 수만큼 블록을 제거해줌
				if (i > 9 - cnt) {
					for (int j = 0; j < 4; ++j) {
						map[i][j] = 0;
					}
				} 
				// 나머지 행의 블록들을 구한 행의 수만큼 이동
				else {
					for (int j = 0; j < 4; ++j) {
						if (map[i][j] == 1) {
							map[i + cnt][j] = 1;
							map[i][j] = 0;
						}
					}
				}
			}
		}

		cnt = 0;

		//연한 blue 영영에 블록이 있는 열의 수를 구함
		for (int j = 4; j <= 5; ++j) {
			for (int i = 0; i < 4; ++i) {
				if (map[i][j] == 1) {
					cnt++;
					break;
				}
			}
		}

		if (cnt > 0) {
			for (int j = 9; j >= 4; --j) {
				// 구한 열의 수만큼 블록을 제거해줌
				if (j > 9 - cnt) {
					for (int i = 0; i < 4; ++i) {
						map[i][j] = 0;
					}
				}
				// 나머지 열의 블록들을 구한 열의 수만큼 이동
				else {
					for (int i = 0; i < 4; ++i) {
						if (map[i][j] == 1) {
							map[i][j + cnt] = 1;
							map[i][j] = 0;
						}
					}
				}
			}
		}
	}

	public static int blockCnt() {
		int cnt = 0;
		for (int i = 0; i < 10; ++i) {
			for (int j = 0; j < 10; ++j) {
				if (map[i][j] == 1) {
					cnt++;
				}
			}
		}
		return cnt;
	}
}

 

 

반응형

댓글