[문제풀이] 리틀 프렌즈 사천성

업데이트:

문제 링크 : 리틀 프렌즈 사천성

풀이 시간 : 50분

1. 문제 풀이

일반 사천성 게임과 비슷한 문제

다른 점은 기존 사천성은 선 3개 이하로 연결했다면 이 문제는 2개 이하로만 연결 가능

모든 블록을 제거하면 제거한 순으로 알파벳 출력

방법이 여러개일 경우 알파벳 순으로 가장 먼저인 방법 출력

1) 각 알파벳 블록들의 위치 저장

2) 알파벳 순으로 리스트에 저장하여 하나씩 가능 여부 체크

2-1) 연결이 가능한 경우, 현재 블록 제거 및 알파벳 저장 후 임시 리스트(temp)에 q에 있는 나머지 블록들 저장

2-2) 불가능한 경우, 임시 리스트(temp)에 현재 블록 저장

3) 제거한 블록이 유무 체크

3-1) 있을 경우, 임시 리스트(temp)의 값을 q에 복사 후 2)번으로 이동

3-2) 없을 경우, IMPOSSIBLE 출력

임시 리스트(temp)를 이용하여 q에서 알파벳의 순서를 유지하게 만듬

2. 소스 코드

    public String solution(int m, int n, String[] board) {
		// 알파벳 블록 저장
		Block[] block = new Block[27];
		int[][] map = new int[m][n];
		char c = 'A';
		for (int i = 1; i < block.length; i++) {
			block[i] = new Block(c);
			c++;
		}
		LinkedList<Block> q = new LinkedList<>();
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				if (board[i].charAt(j) == '.') {
					continue;
				} else if (board[i].charAt(j) == '*') {
					map[i][j] = -1;
				} else {
					int idx = board[i].charAt(j) - 'A' + 1;
					map[i][j] = idx;
					// 처음 만나는 블록인지 확인
					if (block[idx].check) {
						// 두 번째 일 경우 좌표 값 중 왼쪽에 있는 것을 (y1,x1)으로 변경
						if (j > block[idx].x1) {
							block[idx].y2 = i;
							block[idx].x2 = j;
						} else {
							block[idx].y2 = block[idx].y1;
							block[idx].y1 = i;
							block[idx].x2 = block[idx].x1;
							block[idx].x1 = j;
						}
					} else {
						block[idx].y1 = i;
						block[idx].x1 = j;
						block[idx].check = true;
					}
				}
			}
		}
		// 실제로 board에 있는 블록들 저장
		// 알파벳 순서로 저장
		for (int i = 1; i < block.length; i++) {
			if (block[i].check) {
				q.add(block[i]);
			}
		}
		// 결과값
		StringBuilder sb = new StringBuilder();
		LinkedList<Block> temp = new LinkedList<>();
		while (!q.isEmpty()) {
			int size = q.size();
			temp.clear();
			while(!q.isEmpty()) {
				Block b = q.poll();
				boolean flag = true;
				int idx = b.c - 'A' + 1;
				// (y1, x1) 기준으로 (y1, x2)로 갈 수 있는지 체크
				for (int j = b.x1; j <= b.x2; j++) {
					if (map[b.y1][j] == 0 || map[b.y1][j] == idx) {
						continue;
					} else {
						flag = false;
						break;
					}
				}
				// 가능하면
				if (flag) {
					int maxY = Math.max(b.y1, b.y2);
					int minY = Math.min(b.y1, b.y2);
					//  (minY, x2) 기준으로 (maxY, x2) 가능한지 판단
					for (int j = minY; j <= maxY; j++) {
						if (map[j][b.x2] == 0 || map[j][b.x2] == idx) {
							continue;
						} else {
							flag = false;
							break;
						}
					}
					// 가능하면 저장
					if (flag) {
						map[b.y1][b.x1] = 0;
						map[b.y2][b.x2] = 0;
						sb.append(b.c);
						// 나머지는 다시 temp로 이동
						while(!q.isEmpty()) {
							temp.add(q.poll());
						}
						break;
					}
				}
				// 위 조건이 안될 경우
				if (!flag) {
					flag = true;
					int maxY = Math.max(b.y1, b.y2);
					int minY = Math.min(b.y1, b.y2);
					// (minY, x1) 기준으로 (maxY, x1)으로 갈 수 있는지 체크
					for (int j = minY; j <= maxY; j++) {
						if (map[j][b.x1] == 0 || map[j][b.x1] == idx) {
							continue;
						} else {
							flag = false;
							temp.add(b);
							break;
						}
					}
					// 가능한 경우
					if (flag) {
						// (y2, x1) 기준으로 (y2,x2) 갈 수 있는지 체크
						for (int j = b.x1; j <= b.x2; j++) {
							if (map[b.y2][j] == 0 || map[b.y2][j] == idx) {
								continue;
							} else {
								flag = false;
								temp.add(b);
								break;
							}
						}
						// 가능하면 q에 있는 값은 temp 이동
						if (flag) {
							map[b.y1][b.x1] = 0;
							map[b.y2][b.x2] = 0;
							sb.append(b.c);
							while(!q.isEmpty()) {
								temp.add(q.poll());
							}
							break;
						}
					}
				}
			}
			// 아까 q의 사이즈와 temp의 사이즈가 같으면 제거한 블록이 없음
			if (size == temp.size()) {
				return "IMPOSSIBLE";
			}
			// 그러치 않으면 temp를 q에 복사
			q.addAll(temp);
		}
		return sb.toString();
	}

3. 후기

카카오 블라인드 채용이 올라왔다.

준비를 위해서 프로그래머스에 있는 카카오 관련 문제를 다 풀 예정

4. 주의

n = 3, m = 3, board = {“DBF”, “G*F”, “GDB”} 일 경우 답은 “FBGD”

통과가 안됨면 이 테스트 해보기

1) F, G 가능, F가 알파벳 순으로 먼저 이기 때문에 F 제거

2) G, B(F가 제거되어서 가능) 가능, B가 알파벳 순으로 먼저 이기 때문에 B 제거

3) G만 가능 G 제거

4) D만 가능 D 제거