본문 바로가기
Algorithm/백준

[백준] 14503번 : 로봇 청소기 / java

by 코딩친구 2021. 2. 26.
반응형

www.acmicpc.net/problem/14503

 

14503번: 로봇 청소기

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어

www.acmicpc.net

 

 

[ 코드 ]

 

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

public class BOJ_14503_로봇청소기 {
	static int N,M;
	static int r,c,d;
	static int arr[][];
	static int visited[][];
	static boolean flag = true;
	static int dx[] = {-1,0,1,0};
	static int dy[] = {0,1,0,-1};
	
	static int clean = 0;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		
		st = new StringTokenizer(br.readLine());
		r = Integer.parseInt(st.nextToken());
		c = Integer.parseInt(st.nextToken());
		d = Integer.parseInt(st.nextToken());
		//0 위
		//1 오
		//2 아래
		//3 왼
		
		arr = new int[N][M];
		visited = new int[N][M];
		
		for(int i=0; i<N; i++) {
			st = new StringTokenizer(br.readLine());
			for(int j=0; j<M; j++) {
				arr[i][j] = Integer.parseInt(st.nextToken());
				if(arr[i][j]==1) visited[i][j] = 2; // 벽 처리
			}
		}
		
		//1. 현재 위치를 청소한다.
		visited[r][c] = 1;
		clean++;
		
		cleanup();
		
		System.out.println(clean);
		
	}

	private static void cleanup() {
		while(flag) {
			int tmp = 0; // 모든 방향을 확인할 변수
			
			for(int k=3; k>=0; k--) {
				int nr = r+dx[k];
				int nc = c+dy[k];
				if(visited[nr][nc]!=0) {
					tmp++;
				}
			}
			
			//모든 방향이 청소가 되어있거나 벽이면
			if(tmp==4) {
				int behind = (d+2)%4;
				
				int br = r+dx[behind];
				int bc = c+dy[behind];
				
				if(visited[br][bc]==2) { //뒤가 벽이라 후진을 할 수 없다면
					flag = false;
				} else { //아니라면 후진
					r = br;
					c = bc;
				}
			}
			
			//2. 현재 위치 기준 왼쪽부터 청소
			for(int k=1; k<=4; k++) {
				int left = (d-k+4)%4; //현재 기준 왼쪽
				
				int lr = r+dx[left];
				int lc = c+dy[left];
				
				if(visited[lr][lc]==0) {
					visited[lr][lc] = 1;
					clean++;
					r = lr;
					c = lc;
					d = left;
					cleanup();
				}
			}
		}
	}
}

 

 

여기서 2가지 어려운 포인트만 집고 넘어가면 된다.

 

 

1. 왼쪽으로 돌아가는 시뮬레이션을 숫자로 잘 정리하면서 풀자.

 

d를 직관적으로 받기 위해 dx, dy 배열의 순서대로 왼, 오, 아래, 위를 넣어두고

왼쪽으로 돌아가는 것은 반대로 돌아가는 것이기 때문에

dx[3] dx[2] dx[1] dx[0]for문에서 k=3; k>=0; k--로 써주었다.

 

 

2. 청소기 뒤, 청소기 현재 기준 왼쪽 공식을 잘 이해하고 구현하자.

 

뒤 = (d+2)%4

배열에서 의 0,2 가 위 아래 1,2이 오른쪽 왼쪽

 

왼쪽 = (d-k+4)%4

3->2->1->0->3->2->…

 

 

 

 

마지막으로 현재 좌표와 바라보고 있는 방향을

현재 기준으로 저장해주고 다시 시작하면 된다!

 

r,c,d 앞에 StringTokenizer로 다시 깔끔하게 해주는것만 주의하자.

 

 

 

 

※ 오늘의 교훈

하다보니 깔끔하게 통과하는 날도 온다.

저번 교훈이 바로 도움이 되었다.

참고 하나 하지 않고 내 스스로의 힘으로 풀어냈다.

 

구현 시뮬레이션 연습을 더 많이해보자!

반응형