[2564] 경비원

HeeSeong·2024년 9월 27일
0

백준

목록 보기
95/116
post-thumbnail

🔗 문제 링크

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


🔍 문제 설명


동근이는 무인 경비 회사 경비원으로 항상 대기하고 있다가 호출이 들어오면 경비차를 몰고 그 곳으로 달려가야 한다. 동근이가 담당하고 있는 곳은 직사각형 모양의 블록으로 블록 중간을 가로질러 차가 통과할만한 길이 없다. 이 블록 경계에 무인 경비를 의뢰한 상점들이 있다.

예를 들어 가로의 길이가 10, 세로의 길이가 5인 블록의 경계에 무인 경비를 의뢰한 3개의 상점이 있다고 하자. <그림 1>과 같이 이들은 1, 2, 3으로 표시되어 있고, 동근이는 X로 표시한 위치에 있다.

1번 상점에서 호출이 들어 왔을 때 동근이가 블록을 시계방향으로 돌아 이동하면 이동 거리가 12가 된다. 반면 반시계방향으로 돌아 이동하면 이동 거리는 18이 된다. 따라서 동근이가 1번 상점으로 가는 최단 거리는 12가 된다. 마찬가지로 동근이의 위치에서 2번 상점까지의 최단 거리는 6, 3번 상점까지의 최단 거리는 5가 된다.

블록의 크기와 상점의 개수 및 위치 그리고 동근이의 위치가 주어질 때 동근이의 위치와 각 상점 사이의 최단 거리의 합을 구하는 프로그램을 작성하시오.


⚠️ 제한사항


  • 블록의 가로의 길이와 세로의 길이, 상점의 개수는 모두 100이하의 자연수이다.

  • 상점의 위치는 두 개의 자연수로 표시된다.

  • 상점의 위치나 동근이의 위치는 블록의 꼭짓점이 될 수 없다.



🗝 풀이 (언어 : Java)


최단거리 탐색이므로 BFS를 사용해서 탐색했다. 다음 이동 가능 좌표를 가능 케이스별로 나눠서 구현했다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.StringTokenizer;

public class Main {

	private static final int[] dx = {-1, 1, 0, 0}; //상하좌우
	private static final int[] dy = {0, 0, -1, 1};

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int column = Integer.parseInt(st.nextToken());
		int row = Integer.parseInt(st.nextToken());
		int n = Integer.parseInt(br.readLine());
		int[][] stores = new int[n][2];
		for (int i = 0; i < n; i++) {
			StringTokenizer st2 = new StringTokenizer(br.readLine(), " ");
			int n1 = Integer.parseInt(st2.nextToken());
			int n2 = Integer.parseInt(st2.nextToken());
			stores[i] = indexConverter(row, column, n1, n2);
		}
		StringTokenizer st3 = new StringTokenizer(br.readLine(), " ");
		int s1 = Integer.parseInt(st3.nextToken());
		int s2 = Integer.parseInt(st3.nextToken());
		br.close();
		solution(row, column, indexConverter(row, column, s1, s2), stores);
	}

	private static void solution(int row, int column, int[] start, int[][] stores) {
		int sum = 0;
		for (int[] store : stores) {
			boolean[][] visited = new boolean[row + 1][column + 1];
			ArrayDeque<int[]> queue = new ArrayDeque<>() {{
				addLast(start);
			}};
			visited[start[0]][start[1]] = true;
			sum += countStep(row, column, store, queue, visited);
		}
		System.out.println(sum);
	}

	private static int[] indexConverter(int row, int column, int num1, int num2) {
		if (num1 == 1) {
			return new int[] {0, num2};
		} else if (num1 == 2) {
			return new int[] {row, num2};
		} else if (num1 == 3) {
			return new int[] {num2, 0};
		} else {
			return new int[] {num2, column};
		}
	}

	private static int countStep(int row, int column, int[] store, ArrayDeque<int[]> queue, boolean[][] visited) {
		int step = 0;
		while (!queue.isEmpty()) {
			int size = queue.size();
			for (int i = 0; i < size; i++) {
				int[] position = queue.pollFirst();
				if (position[0] == store[0] && position[1] == store[1]) {
					return step;
				}
				int[][] nextPositionArr = nextPositionArray(row, column, position);
				for (int[] next : nextPositionArr) {
					if (next[0] < 0 || next[0] > row || next[1] < 0 || next[1] > column || visited[next[0]][next[1]]) {
						continue;
					}
					queue.addLast(new int[] {next[0], next[1]});
					visited[next[0]][next[1]] = true;
				}
			}
			step++;
		}
		return step;
	}

	private static int[][] nextPositionArray(int row, int column, int[] position) {
		//위쪽 변
		if (position[0] == 0) {
			//좌측 상단 꼭지점, 하 우 이동
			if (position[1] == 0) {
				return new int[][] {{position[0] + dx[1], position[1] + dy[1]}, {position[0] + dx[3], position[1] + dy[3]}};
			}
			//우측 상단 꼭지점, 하 좌 이동
			if (position[1] == column) {
				return new int[][] {{position[0] + dx[1], position[1] + dy[1]}, {position[0] + dx[2], position[1] + dy[2]}};
			}
			//꼭지점 아닌 경우, 좌 우 이동
			return new int[][] {{position[0] + dx[2], position[1] + dy[2]}, {position[0] + dx[3], position[1] + dy[3]}};
		}
		//아래쪽 변
		if (position[0] == row) {
			//좌측 하단 꼭지점, 상 우 이동
			if (position[1] == 0) {
				return new int[][] {{position[0] + dx[0], position[1] + dy[0]}, {position[0] + dx[3], position[1] + dy[3]}};
			}
			//우측 하단 꼭지점, 상 좌 이동
			if (position[1] == column) {
				return new int[][] {{position[0] + dx[0], position[1] + dy[0]}, {position[0] + dx[2], position[1] + dy[2]}};
			}
			//꼭지점 아닌 경우, 좌 우 이동
			return new int[][] {{position[0] + dx[2], position[1] + dy[2]}, {position[0] + dx[3], position[1] + dy[3]}};
		}
		//왼쪽 오른쪽 변, 상 하 이동
		return new int[][] {{position[0] + dx[0], position[1] + dy[0]}, {position[0] + dx[1], position[1] + dy[1]}};
	}

}
profile
끊임없이 성장하고 싶은 개발자

0개의 댓글

관련 채용 정보