🌞Algorithm/🔥Baekjoon

[Baekjoon] 15644_구슬 탈출 3

뿌야._. 2022. 12. 21. 10:02

Gold I

문제(출처: https://www.acmicpc.net/problem/15644)

<구슬 탈출 3 >

 

문제 풀이

 

구슬 탈출 2 (https://melody-coding.tistory.com/266)에서 추가로 어떻게 기울여야 하는지를 구해준다.

기울기를 저장하기 위해 String을 저장하는 queue를 추가로 선언해 준다.

 

 - my solution (Java)

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

public class _15644_ {

	static char map[][];
	static Queue<int[]> R, B;
	static Queue<String> cmd;
	static String cmdresult;
	static int result;
	static int dx[] = { -1, 1, 0, 0 };
	static int dy[] = { 0, 0, -1, 1 };

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());

		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());

		map = new char[n][m];
		result = -1;
		R = new LinkedList<>();
		B = new LinkedList<>();
		cmd=new LinkedList<>();
		for (int i = 0; i < n; i++) {
			String s = bf.readLine();
			for (int j = 0; j < m; j++) {
				map[i][j] = s.charAt(j);
				if (map[i][j] == 'R') {
					R.add(new int[] { i, j, 0 });
					cmd.add("");
				}
				else if (map[i][j] == 'B')
					B.add(new int[] { i, j, 0 });
			}
		}
		search();
		System.out.println(result);
		if(result!=-1)System.out.println(cmdresult);
	}

	private static void search() {
		boolean check = false;

		while (!R.isEmpty()) {
			int[] R_temp = R.poll();
			int[] B_temp = B.poll();
			String a=cmd.poll();
			int x1, y1, x2, y2;
			for (int i = 0; i < 4; i++) {
				cmdresult=a;
				int temp = R_temp[2] + 1;
				if(i==0)cmdresult+="U";
				else if(i==1) cmdresult+="D";
				else if(i==2) cmdresult+="L";
				else cmdresult+="R";
				if (temp > 10)
					break; // 10번 이하가 아니면 x
				x1 = R_temp[0];
				y1 = R_temp[1];
				check = false;
				while (true) { // 빨간 구슬
					x1 += dx[i];
					y1 += dy[i];

					if (map[x1][y1] == '#') {
						break;
					}
					if (map[x1][y1] == 'O') { // 구멍
						check = true;
						break;
					}
				}
				x2 = B_temp[0];
				y2 = B_temp[1];
				while (true) { // 파란 구슬
					x2 += dx[i];
					y2 += dy[i];
					if (map[x2][y2] == 'O') { // 파란구슬이  구멍에 빠지면 실패
						result = -1;
						break;
					}
					if (map[x2][y2] == '#') {
						if (x1 == x2 && y1 == y2) { // 빨간 구슬과 파란 구슬 좌표가 같으면 위치 조정
							if (i == 0) {
								if (B_temp[0] < R_temp[0]) {
									x2 -= dx[i];
									x1 = x2 - dx[i];
								} else {
									x1 -= dx[i];
									x2 = x1 - dx[i];
								}
							} else if (i == 1) {
								if (B_temp[0] < R_temp[0]) {
									x1 -= dx[i];
									x2 = x1 - dx[i];
								} else {
									x2 -= dx[i];
									x1 = x2 - dx[i];
								}
							} else if (i == 2) {
								if (B_temp[1] < R_temp[1]) {
									y2 -= dy[i];
									y1 = y2 - dy[i];
								} else {
									y1 -= dy[i];
									y2 = y1 - dy[i];
								}
							} else {
								if (B_temp[1] < R_temp[1]) {
									y1 -= dy[i];
									y2 = y1 - dy[i];
								} else {
									y2 -= dy[i];
									y1 = y2 - dy[i];
								}
							}
						} else {
							x1 -= dx[i];
							y1 -= dy[i];
							x2 -= dx[i];
							y2 -= dy[i];
							if (check) { // 최소 횟수
								result = temp;
								break;
							}
						}
						if (!(R_temp[0] == x1 && R_temp[1] == y1 && B_temp[0] == x2 && B_temp[1] == y2)) { // 원래 위치와 동일하지 않으면 
							R.add(new int[] { x1, y1, temp });
							B.add(new int[] { x2, y2, temp });
							cmd.add(cmdresult);
						}
						break;
					}
				}
				if (result > 0)
					break;
			}
			if (result > 0)
				break;
		}
	}
}

 

  • 변수 설명
    • map: 보드 
    • R, B: 각각 빨간 구슬, 파란 구슬의 [x 좌표, y 좌표, count]
    • result: 최소 횟수
    • check: 빨간 구슬이 구멍에 들어간 여부 확인
    • cmd: 기울기를 저장하는 queue
    • cmdresult: 기울기
  • main
    • 보드 입력 후 빨간 구슬과 파란 구슬의 위치를 각 queue에 저장
    • search 함수 호출
    • result 출력
  • search
    • 빨간 구슬 queue가 빌 때까지 반복
    • 기울기를 저장해둔 queue인 cmd에서 하나 뽑은 후 상하좌우 경우에 맞게 기울기 추가
    • 각각 구슬 queue에서 하나씩 뽑은 후 상하좌우 이동
      • 빨간 구슬을 움직이며 더 이상 이동할 수 없는 위치라면 탈출
      • 구멍에 빠졌다면 check를 true로 바꾼 후 탈출
      • 파란 구슬을 움직이며 구멍에 빠졌다면 result를 0으로 바꾼 후 탈출
      • 파란 구슬이 더 이상 이동할 수 없는 위치이고 빨간 구슬과 파란 구슬 좌표가 같다면 각각 위치 조정(예를 들어 위로 움직인 경우 파란 구슬이 더 위에 있다면 파란 구슬보다 빨간 구슬이 한 칸 더 밑에 있도록 조정) but 빨간 구슬과 파란 구슬 좌표가 같지 않다면 빨간 구슬이 구멍에 빠진 지 확인 후 빠졌으면 탈출! 구멍에 빠지지 않았다면 이동하기 전 위치와 비교해서 같지 않은 경우에만 queue에 저장 및 기울기 queue에 저장

생각🤔

 

구슬 문제 2에서 기울기 구하는 것만 추가했더니 쉽게 통과할 수 있었다.

 


'🌞Algorithm > 🔥Baekjoon' 카테고리의 다른 글

[Baekjoon] 9019_DSLR  (0) 2022.12.23
[Baekjoon] 12919_A와 B 2  (0) 2022.12.22
[Baekjoon] 13459_구슬 탈출  (0) 2022.12.20
[Baekjoon] 13460_구슬 탈출 2  (0) 2022.12.19
[Baekjoon] 4179_불!  (0) 2022.12.16