[백준 11559] 뿌요뿌요 (자바)
알고리즘/백준

[백준 11559] 뿌요뿌요 (자바)

반응형

백준 11559번 뿌요뿌요 (자바)

 

 

 

출처

www.acmicpc.net/problem/11559

 

11559번: Puyo Puyo

현재 주어진 상황에서 몇연쇄가 되는지 출력하라. (하나도 터지지 않는다면 0을 출력하면 된다.)

www.acmicpc.net

 

 

 

문제

뿌요뿌요의 룰은 다음과 같다.

필드에 여러 가지 색깔의 뿌요를 놓는다. 뿌요는 중력의 영향을 받아 아래에 바닥이나 다른 뿌요가 나올 때까지 아래로 떨어진다.

뿌요를 놓고 난 후, 같은 색 뿌요가 4개 이상 상하좌우로 연결되어 있으면 연결된 같은 색 뿌요들이 한꺼번에 없어진다.

뿌요들이 없어지고 나서 위에 다른 뿌요들이 있다면, 역시 중력의 영향을 받아 차례대로 아래로 떨어지게 된다.

아래로 떨어지고 나서 다시 같은 색의 뿌요들이 4개 이상 모이게 되면 또 터지게 되는데, 터진 후 뿌요들이 내려오고 다시 터짐을 반복할 때마다 1연쇄씩 늘어난다.

터질 수 있는 뿌요가 여러 그룹이 있다면 동시에 터져야 하고 여러 그룹이 터지더라도 한번의 연쇄가 추가된다.

남규는 최근 뿌요뿌요 게임에 푹 빠졌다. 이 게임은 1:1로 붙는 대전게임이라 잘 쌓는 것도 중요하지만, 상대방이 터뜨린다면 연쇄가 몇 번이 될지 바로 파악할 수 있는 능력도 필요하다. 하지만 아직 실력이 부족하여 남규는 자기 필드에만 신경 쓰기 바쁘다. 상대방의 필드가 주어졌을 때, 연쇄가 몇 번 연속으로 일어날지 계산하여 남규를 도와주자!

 

 

 

입력

12*6의 문자가 주어진다.

이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다.

R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.(모두 대문자로 주어진다.)

입력으로 주어지는 필드는 뿌요들이 전부 아래로 떨어진 뒤의 상태(즉 뿌요 아래에 빈 칸이 있는 경우는 없음) 이다.

 

 

 

출력

현재 주어진 상황에서 몇연쇄가 되는지 출력하라. (하나도 터지지 않는다면 0을 출력하면 된다.)

 

 

 

입출력 예

입출력 예 1

 

 

 

접근 방법

 

큰 과정은 3가지다.

첫째, 자신이 뿌요일 때 자신 포함 주변에 4개 이상인지 아닌지 찾기.

두 번째, 4개 이상이면 자신과 색상이 같은 뿌요들 터뜨리기(.으로 만들기).

세 번째, 뿌요 밑에 빈 공간(.)이 있는 경우 아래로 내리기

 

1. 근처 뿌요가 4개 이상인 색상이 여러 개인 경우와 연쇄 개수를 세기 위해 while문을 사용한다.

 

2. 방문하지 않았고, 색상이 있는 상태일 때 자신과 색상이 같은 뿌요 개수를 찾아 4개 이상이면 제거하는 연산을 실행한다.

 

3. 제거 연산은 색상이 같은 인접 뿌요를 모두.으로 만들면 된다.

 

4. 제거 연산을 실행하면 연쇄 개수 + 1 해주고, 없을 시에는 계산을 끝낸다.

 

5. 중력은 맨 아래서부터 실행해야 위로 올라가면서 값을 내릴 수 있으므로 감소하는 반복문을 사용한다.

(* 이때 범위를 잘 설정해야 한다. 중력은 행에만 적용되기 때문에 행 개수만 1 줄이고 열 개수는 줄이면 안 된다.)

 

6.  현재 위치가.이고 위에 뿌요가 있다면, 현재 위치에 뿌요를 넣고 뿌요 자리는. 을 넣는다.

 

7. 6번 연산이 실행되면 빈 곳이 있는 것이므로 연산을 지속하고, 실행되지 않으면 중력이 적용되는 곳이 없기 때문에 중력 연산을 끝낸다.

 

8. 총 연쇄 개수를 출력한다.

 

 

 

내 코드

package dfsbfs;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class PuyoPuyo {
	/**
	 * 백준 11559 뿌요뿌요 (https://www.acmicpc.net/problem/11559)
	 */
	
	private static char[][] map = new char[12][6];
	private static boolean[][] visit = new boolean[12][6];
	
	private static int[] dx = {-1, 0, 1, 0};
	private static int[] dy = {0, 1, 0, -1};
	
	private static int cnt = 0;
	
	public static void main(String[] args) throws IOException {
		
		//여러 색깔
		
		//아래로 떨어짐 -> while
		
		//같은 색 뿌요가 4개이상 상하좌우로 연결되어 있으면 한꺼번에 없어짐
		//-> 좌우상하 탐색시 매개변수로 자신의 색깔 보내기
		//-> 같은친구 있으면 계속 탐색하기, 없으면 끝내고 있으면 모두 .으로 변경한다.
		
		//없어지면 위에 뿌요들이 아래로 떨어짐
		//while문 반복
		
		//터질수 있는 뿌요가 여러개 있다면 동시에 터져야 함
		//색깔을 매개변수로 보내 비교하기
		
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		
		for (int i=0; i<12; i++) {
			String input = reader.readLine();
			char[] c = input.toCharArray();
			for (int j=0; j<6; j++) {
				map[i][j] = c[j];
			}
		}
		
		int result = 0;
		
		//연쇄
		while (true) {
			visit = new boolean[12][6];
			
			//연산 했는지 안했는지 체크
			boolean flag = false;
			
			//같은 것 찾는 연산
			for (int i=0; i<12; i++) {
				for (int j=0; j<6; j++) {
					if (!visit[i][j] && map[i][j] != '.') {
						cnt = 1;
						
						if (findCnt(i,j, map[i][j])) {
							//같은 색의 뿌요 개수 4개 이상일 때 제거하기
							flag = true;
							bfs(i,j,map[i][j]);
						}
						
					}
				}
			}
			
			if (flag) {
				//연쇄증가
				result++;
			} else {
				//연쇄가 없다면 탈출
				break;
			}
			
			//아래로 1칸씩 이동
			while (true) {
				//내려갈 친구들 있는지 체크
				boolean check = false;
				
				//중력!!
				check = gravity(check);
				
				if (!check) {
					//내려갈 친구들 없으면 탈출
					break;
				}
				
			}
			
		}
		
		System.out.println(result);
	}

	private static boolean gravity(boolean check) {
		
		//아래서부터 위로 중력실행
		for (int i=11; i>0; i--) {
			for (int j=5; j>=0; j--) {
				if (map[i][j] == '.' && map[i-1][j] != '.') {
					check = true;
					map[i][j] = map[i-1][j];
					map[i-1][j] = '.';
				}
			}
		}
		return check;
	}

	private static void bfs(int x, int y, char color) {
		
		Queue<Puyo> q = new LinkedList<Puyo>();
		
		q.add(new Puyo(x, y));
		
		while (!q.isEmpty()) {
			Puyo py = q.remove();
			
			int qx = py.x;
			int qy = py.y;
			
			for (int i=0; i<dx.length; i++) {
				int nx = qx + dx[i];
				int ny = qy + dy[i];
				
				if (nx < 0 || ny < 0 || nx >= 12 || ny >= 6 || map[nx][ny] != color) {
					continue;
				}
				
				if (visit[nx][ny] && map[nx][ny] == color) {
					//이전 개수셀 때 방문했고 색상이 같으면 .으로 변경(터뜨리기)
					map[nx][ny] = '.';
					q.add(new Puyo(nx, ny));
				}
			}
			
		}
		
	}

	private static boolean findCnt(int x, int y, char color) {
		
		visit[x][y] = true;
		
		for (int i=0; i<dx.length; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			
			if (nx < 0 || ny < 0 || nx >= 12 || ny >= 6 || map[nx][ny] != color) {
				continue;
			}
			
			if (!visit[nx][ny] && map[nx][ny] == color) {
				//인접한 곳중 색상이 같으면 카운트+1
				cnt++;
				findCnt(nx, ny, color);
			}
		}
		
		if (cnt >= 4) {
			return true;
		}
		return false;
		
	}
}


class Puyo {
	int x, y;
	
	public Puyo(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

 

 

 

고려할 점

1. 어떤 부분에서 어떤 연산을 해야 하는지 생각할 것

2. 중력 연산 시 범위를 꼼꼼하게 검사할 것

 

 

반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준 16236] 아기 상어 (자바)  (0) 2020.11.14
[백준 12851] 숨바꼭질2 (자바)  (0) 2020.11.06
[백준 2568] 치즈 (자바)  (0) 2020.11.03
[백준 6593] 상범 빌딩 (자바)  (0) 2020.11.03
[백준 7569] 토마토 (자바)  (0) 2020.10.28