본문 바로가기
Problem Solving/백준

백준 5213 : 과외맨

by Libi 2021. 7. 7.
반응형

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

 

5213번: 과외맨

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 500) 다음 줄부터 N*N-N/2줄(/는 정수 나눗셈이다)에는 두 양의 Ai와 Bi가 주어진다. (1 ≤ Ai, Bi ≤ 6, 1 ≤ i ≤ N * N - N / 2) 타일 i의 왼쪽에 쓰여 있는 숫자는 Ai, 오른

www.acmicpc.net

[ 문제풀이 ]

지문이 굉장히 길어서 이해하는데 조금 시간이 걸렸지만 결국 1번 타일부터 시작하여 각 타일들을 통해 이동할 수 있는 타일 중 번호가 가장 큰 타일의 최소 경로를 찾아주면 되는 문제이다.

이동할 수 있는 타일 간의 거리는 1이기 때문에 BFS를 수행해주면 된다. 다만, 각 타일마다 이동할 수 있는 경로를 어떻게 설정해줄 것인지가 문제이다.

기본적으로 타일이 이동할 수 있는 경로는 6개이다. 하지만 각 층마다 모서리에 있는 타일들은 이동할 수 있는 경로가 제한된다.

이는 홀수 층의 좌우측 타일, 짝수 층의 좌우측 타일, 나머지 타일, 총 5가지 타입의 타일이 존재한다. 또한, 우측의 타일은 현재 타일의 right 값과 동일할 때 이동할 수 있으며, 좌측의 타일은 현재 타일의 left 값과 동일할때 이동할 수 있다.

따라서 타일들을 입력받을때 총 5가지 타입에 따라 타일을 배정해줘서 bfs를 수행할때 이동할 수 있도록 구현해준다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {

	static class Node {
		int idx, left, right, flag, move;

		/**
		 * @param flag : 타일의 위치, 0=나머지/1=홀수 좌측/2=홀수 우측/3=짝수 좌측/4=짝수 우측
		 */
		public Node(int idx, int left, int right, int flag, int move) {
			this.idx = idx;
			this.left = left;
			this.right = right;
			this.flag = flag;
			this.move = move;
		}
	}

	static final int INF = (int)1e9;
	static int N, size;
	static Node[] node;
	static int[] dist, path;
	static boolean[] visit;
	static Stack<Integer> stack;
	static int[][] dir;

	public static void main(String[] args) {
		try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
				BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))){
			N = Integer.parseInt(br.readLine());
			size = N * N - N / 2;
			node = new Node[size + 1];
			visit = new boolean[size + 1];
			dist = new int[size + 1];
			path = new int[size + 1];
			/**
			 *  -N(5)  -N+1(0)
			 *-1(4)  idx   1(1)
			 *  N-1(3)   N(2)   
			 */
			dir = new int[][] {{-N+1, 1, N, N-1, -1, -N},
				{-N+1, 1, N},
				{0, 0, 0, N-1, -1, -N},
				{-N+1, 1, N, N-1, 0, -N},
				{-N+1, 0, N, N-1, -1, -N}
			};
			stack = new Stack<>();

			int level = 1, cnt = 0, left = 1, right = N;
			for (int i = 1; i <= size; ++i) {
				StringTokenizer st = new StringTokenizer(br.readLine());
				int A = Integer.parseInt(st.nextToken());
				int B = Integer.parseInt(st.nextToken());

				cnt++;
				if (level % 2 == 1) {
					if (i == left) node[i] = new Node(i, A, B, 1, 1);
					else if (i == right) node[i] = new Node(i, A, B, 2, 1);
					else node[i] = new Node(i, A, B, 0, 1);

					if (cnt % N == 0) {
						level++;
						cnt = 0;
						left += N;
						right += N - 1;
					}
				} else {
					if (i == left) node[i] = new Node(i, A, B, 3, 1);
					else if (i == right) node[i] = new Node(i, A, B, 4, 1);
					else node[i] = new Node(i, A, B, 0, 1);

					if (cnt % (N - 1) == 0) {
						level++;
						cnt = 0;
						left += N - 1;
						right += N;
					}
				}
			}

			bfs();

			for (int i = size; i >= 1; --i) {
				if (dist[i] != INF) {
					bw.write(dist[i] + "\n");
					getPath(i);
					while (!stack.isEmpty()) {
						bw.write(stack.pop() + " ");
					}
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void bfs() {
		Arrays.fill(dist, INF);
		Queue<Node> q = new LinkedList<>();
		q.offer(node[1]);
		dist[1] = 1;
		visit[1] = true;

		while (!q.isEmpty()) {
			Node n = q.poll();

			for (int i = 0; i < dir[n.flag].length; ++i) {
				if (dir[n.flag][i] == 0) continue;

				int nv = n.idx + dir[n.flag][i];

				if (nv <= 0 || nv > size || visit[nv]) continue;
				if (i <= 2) {
					if (n.right != node[nv].left) continue;
				} else {
					if (n.left != node[nv].right) continue;
				}

				visit[nv] = true;
				dist[nv] = n.move + 1;
				path[nv] = n.idx;
				q.offer(new Node(nv, node[nv].left, node[nv].right, node[nv].flag, n.move + 1));
			}
		}
	}

	public static void getPath(int v) {
		if (v == 0) return;
		stack.add(v);
		getPath(path[v]);
	}
}
반응형

'Problem Solving > 백준' 카테고리의 다른 글

백준 1781 : 컵라면  (0) 2021.07.11
백준 15483 : 최소 편집  (0) 2021.07.08
백준 2662 : 기업투자  (0) 2021.07.06
백준 2211 : 네트워크 복구  (0) 2021.07.05
백준 1525 : 퍼즐  (0) 2021.07.04

댓글