Algorithms

[BOJ] 14503번 로봇청소기 Java 풀이

SDev 2021. 6. 19. 14:10
728x90

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

public class Main {
	// 환경 속성
	static int N, M;
	static int room[][];
	static boolean isClean[][];
	// 청소기 속성
	static int direction;
	static int row, col;
	static int count = 0;

	public static void main(String[] args) throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		
		room = new int[N][M];
		isClean = new boolean[N][M];
		
		st = new StringTokenizer(br.readLine());
		row = Integer.parseInt(st.nextToken());
		col = Integer.parseInt(st.nextToken());
		direction = Integer.parseInt(st.nextToken());
		
		for(int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());
			for(int j = 0; j < M; j++) {
				room[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		run();
		System.out.println(count);
		
	}
	
	// 청소기 작동 메서드
	static void run() {
		while(true) {
			// 1. 현재 위치를 청소
			clean();
			// 2. 현재 방향 기준 왼쪽 방향부터 탐색 진행
			
			// a) 왼쪽 방향에 청소할 공간 있다면
			if(inspectLeft(direction)) {
				// 회전하고 한 칸 전진후 1번 진행
				// 회전
				direction -= 1;
				if(direction == -1) {
					direction = 3;
				}
				
				// 방향으로 전진
				if(direction == 0) {		// 북
					// 갈 수 있으면
					if(row > 1 && room[row-1][col] != 1)
					row -= 1;
				}else if(direction == 1) {	// 동
					if(col < M && room[row][col+1] != 1)
					col += 1;
				}else if(direction == 2) {	// 남
					if(row < N && room[row+1][col] != 1)	
					row += 1;
				}else {						// 서 
					if(col > 1 && room[row][col-1] != 1)
					col -= 1;
				}
//				System.out.println(100);
//				System.out.println(direction+", "+row+","+col);
//				try {
//					Thread.sleep(300);
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
				continue;
			}else {
				// c) 네 방향 모두 청소할 공간이 없다면 한 칸 후진
				if(!inspectLeft(0) && !inspectLeft(1) && !inspectLeft(2) && !inspectLeft(3)) {
					if(direction == 0) {	// 북
						row += 1;
						// d) 후진이 불가능한 경우 작동을 멈춤 
						if(row == N || room[row][col] == 1) {
							break;
						}
					}else if(direction == 1) {	// 동
						col -= 1;
						// d) 후진이 불가능한 경우 작동을 멈춤 
						if(col == -1 || room[row][col] == 1) {
							break;
						}
					}else if(direction == 2) {	// 남
						row -= 1;
						// d) 후진이 불가능한 경우 작동을 멈춤 
						if(row == -1 || room[row][col] == 1) {
							break;
						}
					}else {	// 서
						col += 1;
						// d) 후진이 불가능한 경우 작동을 멈춤 
						if(col == M || room[row][col] == 1) {
							break;
						}
					}
//					System.out.println(101);
				}else {
					// b) 왼쪽은 없지만 다른 방향 청소가 가능하면 좌회전하고 2번으로 돌아감
					direction -= 1;
					if(direction == -1) {
						direction = 3;
					}
//					System.out.println(102);
					// clean 함수가 이미 청소한 칸에서는 횟수를 세지 않도록 동작시키면 1번으로 돌려보내도 됌
					continue;
				}
			}
		}
	}
	
	// 왼쪽 방향에 청소할 공간 있는지 확인
	static boolean inspectLeft(int dir) {
		if(dir == 0) {	// 북쪽 방향을 바라보는 경우
			if(col > 0) {
				if(room[row][col-1] == 0 && isClean[row][col-1] == false) return true;
			}
			// 청소할 공간 없었다면 false 반환
			return false;
		}
		
		else if(dir == 1) {	// 동쪽 방향을 바라보는 경우
			if(row > 0) {
				if(room[row-1][col] == 0 && isClean[row-1][col] == false) return true;
			}
			// 청소할 공간 없었다면 false 반환
			return false;
		}
		
		else if(dir == 2) {	// 남쪽 방향을 바라보는 경우
			if(col < M - 1) {
				if(room[row][col+1] == 0 && isClean[row][col+1] == false) return true;
			}
			// 청소할 공간 없었다면 false 반환
			return false;
		}
		
		else {	// 서쪽 방향을 바라보는 경우
			if(row < N - 1) {
				if(room[row+1][col] == 0 && isClean[row+1][col] == false) return true;
			}
			// 청소할 공간 없었다면 false 반환
			return false;
		}
	}
	
	// 청소 시행 및 횟수 카운트 메서드
	static void clean() {
		if(isClean[row][col] == false && room[row][col] == 0) {
//			System.out.println(row+", "+col + ": 청소 완료");
			isClean[row][col] = true;
			count++;
		}
	}
}