my study.

Coding Test/Baekjoon

[백준] 11559 Puyo Puyo, java

fftl 2023. 9. 4. 20:02

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

 

11559번: Puyo Puyo

총 12개의 줄에 필드의 정보가 주어지며, 각 줄에는 6개의 문자가 있다. 이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다. R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.

www.acmicpc.net

문제 이해

 

문제를 읽어보면 특별히 어렵지 않게 이해할 수 있는 문제였습니다. 중력에 의해 떨어지는 블록이 존재하고 상하좌우 같은 블록이 4개 이상 연결되어 있으면 삭제될 수 있습니다. 4개 이상 연결되어 있는 블럭의 그룹이 한 개 이상일 경우 그 블록들은 동시에 사라져야 하며 이렇게 한 번 사라지는 동작을 한 번의 연쇄라고 합니다. 또 이렇게 블록이 사라져 공중에 떠 있는 블록이 생긴다면 중력에 의해 아래 방향으로 내려와야 합니다.

 

문제에서 블럭이 주어질 때 몇 연쇄가 일어날 수 있는지 반환하시오.라는 문제입니다.

 

문제의 요점은

  • 상하좌우 네 개 이상 연결되어 있는 블럭을 찾아내는 것
  • 여러 블럭의 그룹이 사라져야 할 때 동시에 삭제하기
  • 중력이 적용되어 떨어지는 블록의 움직임 구현하기

이렇게 세 가지를 어떻게 구현하느냐 였던 것 같습니다. 그래도 이 같이 구현하는 문제는 조금 적응이 된 저로서는 어렵지 않게 문제를 구상하였고, 크게 오랜 시간을 들이지 않아서 풀어낼 수 있었습니다. 문제에 대한 풀이는 주석을 통해서 서술하도록 하겠습니다.

 

public class Main {
	static char[][] board;
	static int[] dy = {0, 0, 1, -1};
	static int[] dx = {1, -1, 0, 0};
	static int cnt;
	static ArrayList<ArrayList<int[]>> nodes;
	static boolean[][] visited;
	
	public static void main(String[] args) throws Exception{
		board = new char[12][6];
		
		cnt = 0;
		nodes = new ArrayList<ArrayList<int[]>>();
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		for (int i = 0; i < 12; i++) {
			board[i] = br.readLine().toCharArray();
		}
		
		//뿌요가 4개이상 연결 된 것이 없을 때 까지 반복해줍니다.
		while(true) {
			visited = new boolean[12][6];
			int nowCnt = 0; //연결된 뿌요가 4개이상 존재하는 즉 영역의 개수를 세어줍니다.
			
			//모든 좌표를 확인하여 줍니다.
			for (int i = 0; i < 12; i++) {
				for (int j = 0; j < 6; j++) {
					
					//블럭이 존재한다면 탐색을 시작합니다.
					if(board[i][j] != '.' && !visited[i][j]) {
						
						//현재 위치의 블럭이 무엇인지 담아두고
						//해당 블럭의 좌표를 담아줍니다.
						char nowC = board[i][j];  
						nodes.add(new ArrayList<int[]>());
						nodes.get(nowCnt).add(new int[] {i, j});
						
						//4방향을 탐색하기 위한 bfs를 위한 q를 생성합니다.
						//그리고 현재 위치는 미리 방문표시 해놓습니다.
						Queue<int[]> q = new LinkedList<>();
						q.add(new int[] {i, j});
						visited[i][j] = true;
						
						while(!q.isEmpty()) {
							//현재 노드를 꺼내어주고
							int[] node = q.poll();
							
							//상하좌우 중 같은 뿌요를 가진 것들을 찾아 q에 추가해줍니다.
							for (int k = 0; k < 4; k++) {
								int ny = node[0] + dy[k];
								int nx = node[1] + dx[k];
								
								//범위 안에 존재하고, 아직 방문한적이 없고, 같은 뿌요일 경우
								//방문처리 해주고, 같은 뿌요의 무리에 추가, 그리고 q에 추가해줍니다.
								if(0<=ny && ny<12 && 0<=nx && nx<6 && !visited[ny][nx] && board[ny][nx] == nowC) {
									visited[ny][nx] = true;
									nodes.get(nowCnt).add(new int[] {ny, nx});
									q.add(new int[] {ny, nx});
								}
							}
						}
						
						//현재 담겨진 뿌요가 4개 이상이라면 사라져야할 뿌요입니다.
						//4보다 작다면 해당 뿌요는 remove 해줍니다.
						if(nodes.get(nowCnt).size()>=4) {
							nowCnt++;
						} else {
							nodes.remove(nowCnt);
						}
					}
				}
			}
			
			//위의 과정을 통해서 이번 맵에 사라져야 할 뿌요 그룹이 하나라도 존재한다면
			//해당 뿌요들을 모두 '.'으로 변경해줍니다.
			if(nowCnt>0) {
				for (int i = 0; i < nodes.size(); i++) {
					ArrayList<int[]> now = nodes.get(i);
					for (int j = 0; j < now.size(); j++) {
						int[] nowNode = now.get(j);
						board[nowNode[0]][nowNode[1]] = '.';
					}
				}
				
				cnt++; //현재 위치의 블럭을 담아주고 
				nodes.clear(); //그리고 다음 탐색을 위해 nodes를 비워주고
				gravity();	   //중력을 적용시켜 줍니다.
				
			//사라질 뿌요가 하나도 없다면 반복을 바로 중단시켜버립니다.
			} else {
				break;
			}
			
		}
		
		//정답 출력!!
		System.out.println(cnt);
	}
	
	//중력이 적용하는 모습을 보여줍니다.
	static void gravity() {
		
		//스택 자료구조를 이용해 중력을 표현해 주었습니다.
		Stack<Character> st = new Stack<>();
		
		//세로로 한 줄씩 탐색하며 나오는 블럭들을 스택에 담아주었고,
		//탐색이 끝 난 뒤 해당 줄의 가장 하단부터 하나씩 꺼내어 줌으로서 중력을 표현하였습니다.
		for (int i = 0; i < 6; i++) {
			
			//블럭 찾기
			for (int j = 0; j < 12; j++) {
				if(board[j][i] != '.') {
					st.add(board[j][i]);
					board[j][i] = '.';
				}
			}
			
			//가장 아래부터 하나씩 쌓아주기
			int idx = 11;
			while(!st.isEmpty()) {
				board[idx][i] = st.pop();
				idx--;
			}
		}
	}
	
}

그래도 시뮬레이션 문제에 있어서는 쪼오오오오금 자신이 있을지도..

'Coding Test > Baekjoon' 카테고리의 다른 글

[백준] 23971 ZOAC4, java  (0) 2024.08.13
[백준] 2933 미네랄, java  (0) 2024.07.30
[백준] 15591 MooTube, java  (0) 2023.09.03
[백준] 1806 부분합, java  (0) 2023.05.09
[백준] 2251 물통, java  (0) 2023.04.18