반응형
Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
11-07 11:40
관리 메뉴

ImJay

[BOJ/Java] 2174. 로봇 시뮬레이션 본문

알고리즘/BOJ - Java

[BOJ/Java] 2174. 로봇 시뮬레이션

ImJay 2024. 4. 22. 14:08
반응형

[BOJ/Java] 2174. 로봇 시뮬레이션

 

2174번: 로봇 시뮬레이션

첫째 줄에 두 정수 A, B가 주어진다. 다음 줄에는 두 정수 N, M이 주어진다. 다음 N개의 줄에는 각 로봇의 초기 위치(x, y좌표 순) 및 방향이 주어진다. 다음 M개의 줄에는 각 명령이 명령을 내리는 순

www.acmicpc.net


문제 해석

이 문제는 격자 위에서 주어진 명령에 따라 로봇들을 움직이면서, 로봇이 벽에 부딪히거나 다른 로봇과 충돌하는 상황을 시뮬레이션하는 문제이다. 로봇은 네 방향 중 하나를 향하고 있으며, "F", "L", "R" 세 가지 명령을 수행할 수 있다. "F"는 전진, "L"은 좌회전, "R"은 우회전을 의미한다. 명령에 따라 로봇이 이동할 때마다 그 결과를 검사하여 충돌이나 벽에 부딪히는 상황을 감지해야 한다.

풀이 과정

이 자바 코드는 로봇의 위치, 방향, 그리고 이동 로직을 포함한다. 로봇은 Robot 클래스의 인스턴스로 관리되며, 격자는 maps 배열로 표현된다. maps 배열은 로봇의 위치 정보를 저장하고, 로봇들은 robots 배열에 저장된다.

 

  1. 입력 처리: 격자의 크기, 로봇의 수, 명령의 수를 입력받는다. 그 다음 각 로봇의 초기 위치와 방향을 입력받아 maps와 robots 배열에 저장한다.
  2. 명령 실행: 각 명령을 받아서 해당 로봇을 이동시키는 move 메소드를 호출한다. 이 메소드는 로봇의 이동, 회전을 처리하며, 로봇이 다른 로봇에 충돌하거나 벽에 부딪히는 경우 적절한 값을 반환한다.
  3. 충돌 및 벽 충돌 처리: move 메소드에서 반환된 값에 따라 충돌 메시지를 출력하거나 모든 명령이 성공적으로 수행되었으면 "OK"를 출력한다.

코드

package edu.ssafy.im.BOJ.Gold.G5.No2174;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class Main {
	static int A, B, N, M;

	static class Robot {
		int r, c, d; // 로봇의 위치(r, c)와 방향(d)

		public Robot(int r, int c, int d) {
			this.r = r;
			this.c = c;
			this.d = d;
		}
	}

	static int dr[] = { -1, 0, 1, 0 }; // 방향 벡터 (북, 동, 남, 서)
	static int dc[] = { 0, 1, 0, -1 };
	static Robot[] robots; // 로봇 객체 배열
	static int maps[][]; // 격자 정보 (로봇의 위치 저장)

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringBuilder sb = new StringBuilder();
		StringTokenizer st = new StringTokenizer(br.readLine());
		A = Integer.parseInt(st.nextToken()); // 가로 크기
		B = Integer.parseInt(st.nextToken()); // 세로 크기
		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken()); // 로봇 수
		M = Integer.parseInt(st.nextToken()); // 명령 수
		robots = new Robot[N + 1];
		maps = new int[B + 1][A + 1]; // 격자 초기화

		for (int i = 1; i <= N; i++) {
			st = new StringTokenizer(br.readLine());
			int c = Integer.parseInt(st.nextToken());
			int r = Integer.parseInt(st.nextToken());
			String o = st.nextToken(); // 방향 문자
			maps[B - r + 1][c] = i; // 격자에 로봇 번호 할당
			switch (o) {
			case "N":
				robots[i] = new Robot(B - r + 1, c, 0);
				break;
			case "E":
				robots[i] = new Robot(B - r + 1, c, 1);
				break;
			case "S":
				robots[i] = new Robot(B - r + 1, c, 2);
				break;
			case "W":
				robots[i] = new Robot(B - r + 1, c, 3);
				break;
			}
		}

		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine());
			int robotNum = Integer.parseInt(st.nextToken());
			String order = st.nextToken();
			int loopCnt = Integer.parseInt(st.nextToken());
			int result = move(robotNum, order, loopCnt);
			if (result == -1) { // 벽 충돌 처리
				sb.append("Robot ").append(robotNum).append(" crashes into the wall");
				bw.write(sb.toString());
				bw.flush();
				bw.close();
				return;
				
			}
			if (result > 0) { // 다른 로봇과의 충돌 처리
				sb.append("Robot ").append(robotNum).append(" crashes into robot ").append(result);
				bw.write(sb.toString());
				bw.flush();
				bw.close();
				return;
			}
		}

		sb.append("OK"); // 모든 명령 성공 처리
		
		bw.write(sb.toString());
		bw.flush();
		bw.close();
	}

	private static int move(int robotNum, String order, int loopCnt) {
		for (int i = 0; i < loopCnt; i++) {
			switch (order) {
			case "F":
				maps[robots[robotNum].r][robots[robotNum].c] = 0; // 현재 위치 초기화
				int r = robots[robotNum].r += dr[robots[robotNum].d];
				int c = robots[robotNum].c += dc[robots[robotNum].d];
				if (r <= 0 || r > B || c <= 0 || c > A) return -1; // 벽 충돌 검사
				if (maps[r][c] != 0) return maps[r][c]; // 다른 로봇과 충돌 검사
				maps[robots[robotNum].r][robots[robotNum].c] = robotNum; // 업데이트된 위치에 로봇 번호 할당
				break;
			case "L":
				robots[robotNum].d--; // 방향 왼쪽 회전
				robots[robotNum].d = robots[robotNum].d == -1 ? 3 : robots[robotNum].d;
				break;
			case "R":
				robots[robotNum].d++; // 방향 오른쪽 회전
				robots[robotNum].d = robots[robotNum].d == 4 ? 0 : robots[robotNum].d;
				break;
			}
		}
		return 0;
	}
}

시간 복잡도 분석

시간 복잡도는 주어진 명령의 수 𝑀과 각 명령에서 반복되는 최대 횟수 𝑙𝑜𝑜𝑝𝐶𝑛𝑡에 의해 결정된다. 최악의 경우, 각 명령이 격자의 최대 크기에 걸쳐 반복될 수 있으며, 이는 𝑂(𝑀×𝑙𝑜𝑜𝑝𝐶𝑛𝑡)으로 표현할 수 있다.

느낀점

이 문제를 통해 격자와 객체지향 프로그래밍을 활용한 복잡한 시뮬레이션 로직 구현의 중요성을 다시 한번 깨달았다. 추가로 예외 상황 처리의 중요성도 인지할 수 있었다. 또한, 로봇의 이동과 관련된 여러 경우의 수를 철저히 디버깅하면서 문제 해결 능력이 향상되었다고 느낀다.

반응형

'알고리즘 > BOJ - Java' 카테고리의 다른 글

[BOJ/Java] 14500. 테트로미노  (0) 2024.04.22
[BOJ/Java] 3055. 탈출  (0) 2024.04.22
[BOJ/Java] 11403. 경로 찾기  (1) 2024.04.21
[BOJ/Java] 15652. N과 M (4)  (1) 2024.04.21
[BOJ/Java] 1463. 1로 만들기  (0) 2024.04.21
Comments