[백준] 2174: 로봇 시뮬레이션 (Java)

Yoon Uk·2022년 7월 17일
0

알고리즘 - 백준

목록 보기
34/130
post-thumbnail
post-custom-banner

문제

BOJ 2174: 로봇 시뮬레이션 https://www.acmicpc.net/problem/2174

풀이

  • 문제에서 제시하는 좌표값과 방향2차원 배열로 생각할 때의 좌푯값과 방향과 다르기 때문에 헷갈리기 쉽다.
  • HashMapKey: 로봇의 번호, Value: 로봇의 정보(x 좌표, y 좌표, 현재 바라보고 있는 방향)을 넣는다.
  • 이 때 배열 map의 해당 좌표의 값을 로봇의 번호로 바꾼다.
  • 명령을 받는다.
    • 앞으로 전진하는 명령
      • 전진하며 새롭게 얻은 좌표를 사용하여 벽에 충돌할 때와 다른 로봇과 충돌할 때 각각 알맞은 출력을 해주고 종료한다.
      • 위의 종료 상황이 아니면 로봇의 원래 위치의 값을 0으로 바꿔주고 새로운 위치의 값을 로봇의 번호로 바꿔준다.
      • HashMap에서 원래 있던 로봇의 값을 삭제하고 새로운 위치를 가진 값으로 바꿔 다시 삽입한다.
    • 좌, 우로 방향만 바꾸는 명령
      • HashMap에서 원래 있던 로봇의 값을 삭제하고 새로운 방향을 가진 값으로 바꿔 다시 삽입한다.
  • 위의 종료 상황을 만나지 못하면 "OK"를 출력한다.

코드

import java.util.*;
import java.io.*;

public class Main {
	
	static int A, B, N, M;
	static int[][] map; // 로봇이 움직일 면적 배열
	static HashMap<Integer, Robot> hash = new HashMap<>(); // 로봇 번호 , 로봇 위치
	
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		A = Integer.parseInt(st.nextToken()); // 땅 가로 크기
		B = Integer.parseInt(st.nextToken()); // 땅 세로 크기
		map = new int[B+1][A+1]; // 입력받는 좌표가 1부터 시작하기 때문에 배열을 하나 더 크게 잡는다.
		
		st = new StringTokenizer(br.readLine(), " ");
		N = Integer.parseInt(st.nextToken()); // 로봇 갯수
		M = Integer.parseInt(st.nextToken()); // 명령 갯수
		
		// 로봇 갯수만큼 입력받음
		for(int i=1; i<=N; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			int y = Integer.parseInt(st.nextToken()); 
			int x = Integer.parseInt(st.nextToken());
			char dir = st.nextToken().charAt(0); // 문자로 받은 로봇의 방향
			
            // HashMap에 로봇의 번호를 Key 값으로하여 삽입한다.
			hash.put(i, new Robot(x, y, dir));
			
			// 로봇이 있는 위치는 로봇의 번호를 넣음
			map[x][y] = i;
		}
		
		// 명령 시작
		for(int i=0; i<M; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			int robotNum = Integer.parseInt(st.nextToken()); // 로봇 번호
			char order = st.nextToken().charAt(0); // 명령
			
			int repNum = Integer.parseInt(st.nextToken()); // 명령 반복 횟수

			Robot rob = hash.get(robotNum);
			
			// 앞으로 전진할 때
			if(order == 'F') {
				int nX = rob.x;
				int nY = rob.y;
				for(int r=0; r<repNum; r++) {
					// 새롭게 구한 좌표를 arr 배열로 반환함
					int[] arr = setNewPosition(rob.dir, nX, nY);
					nX = arr[0]; // 새롭게 구한 로봇의 X좌표
					nY = arr[1]; // 새롭게 구한 로봇의 Y좌표
					
					// 벽에 충돌
					if(nX <= 0 || nY <= 0 || nX > B || nY > A) {
						System.out.println("Robot "+ robotNum +" crashes into the wall");
						return;
					}
					
					// 다른 로봇과 충돌
					if(map[nX][nY] != 0) {
						System.out.println("Robot "+ robotNum +" crashes into robot "+ map[nX][nY]);
						return;
					}
	
				}
				// 로봇 최종 위치 갱신
				// 원래 잇엇던 위치는 0으로 다시 바꿈
				map[rob.x][rob.y] = 0;
				hash.remove(robotNum); // 새롭게 넣을 값과 중복되지 않도록 삭제
				// 새롭게 HashMap에 넣고 새로운 위치에 로봇 번호 넣음
				hash.put(robotNum, new Robot(nX, nY, rob.dir));
				map[nX][nY] = robotNum;
				
			} 
			// 방향만 바꿀 때
			else if(order == 'L' || order == 'R') {
				char newDir = rob.dir;
				for(int r=0; r<repNum; r++) {
					newDir = setTurnOrder(robotNum, newDir, order);
				}
				// HashMap에 새롭게 로봇 번호와 새로운 위치, 방향을 넣어줌
				hash.remove(robotNum);
				hash.put(robotNum, new Robot(rob.x, rob.y, newDir));
			}

		} // 명령 끝
		
		System.out.println("OK");
		
	}
	
	static int[] setNewPosition(char robotHead, int robX, int robY) {
    	/*
        * robotHead: 로봇의 현재 방향
        * robX: 로봇의 현재 X좌표
        * robY: 로봇의 현재 Y좌표
        *
        * 문제에서 제시하는 좌표, 방향과 2차원 배열에서의 좌표, 방향이 다르기 때문에 
        * N과 S에서 값을 잘 처리해줘야한다.
        */
		int newX = robX;
		int newY = robY;
		int[] arr = new int[2];
		switch(robotHead) {
			case 'E':
				newY += 1;
				break;
			
			case 'N':
				newX += 1;
				break;
			
			case 'W':
				newY -= 1;
				break;
			
			case 'S':
				newX -= 1;
				break;
			default:
				break;
		}
		arr[0] = newX;
		arr[1] = newY;
		
		return arr;
	}
	
	static char setTurnOrder(int robotNum, char robotHead, char order) {
		/*
		 * robotNum: 로봇 번호
		 * robotHead: 로봇이 바라보는 방향
		 * order: 명령 종류
		 */
		char newDir;
		switch(order) {
			case 'L': newDir = changeDir(robotHead, 'L');
				return newDir;

			case 'R': newDir = changeDir(robotHead, 'R');
				return newDir;

			default:
				break;
		}
		return 'a';
	}
	
	// 방향 바꾸는 메소드
	static char changeDir(char robotHead, char dir) {
   		 /*
		 * robotHead: 현재 로봇이 바라보는 방향
		 * dir: 명령 받은 방향
		 */
		switch(robotHead) {
		case 'E':
			if(dir == 'L') {
				return 'N';
			} else if(dir == 'R') {
				return 'S';
			}
		case 'S':
			if(dir == 'L') {
				return 'E';
			} else if(dir == 'R') {
				return 'W';
			}
		case 'W':
			if(dir == 'L') {
				return 'S';
			} else if(dir == 'R') {
				return 'N';
			}
		case 'N':
			if(dir == 'L') {
				return 'W';
			} else if(dir == 'R') {
				return 'E';
			}
		default: 
			break;
		}
		return 'a';
	}
	
	static class Robot{
		int x, y;
		char dir;
		
		Robot(int x, int y, char dir){
			this.x = x;
			this.y = y;
			this.dir = dir;
		}
	}
}

정리

  • 문제에서 제시하는 좌표, 방향과 문제 해결에 사용하는 2차원 배열에서의 좌표, 방향이 달라서 헷갈렸다.
post-custom-banner

0개의 댓글