코딩문제 풀이

14503번 로봇 청소기

student513 2020. 1. 15. 15:15
 

14503번: 로봇 청소기

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북중 하나이다. 지도의 각 칸은 (r, c)로 나타낼 수 있고, r은 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로 부터 떨어진 칸의 개수이다. 로봇 청소기는 다음

www.acmicpc.net

처음봤을 때 조건이 너무 헷깔리는 문제였다.

 

관련 질문글을 봐도 문제 정정요청이 수두룩한 문제...

 

직접 워드로 표를 만들면서 디버깅했다.

 

구조체에 로봇의 위치와 방향에 관한 정보를 저장하는 것은 필수이다.

 

본 코드의 핵심은 입력된 좌표파라미터가 청소 가능한 좌표인지

 

혹은 모종의 이유로(벽이거나 이미 청소 되어있거나) 청소할 수 없는 좌표인지를 판단하는 

 

bool clean_move 함수이다.

 

이를 통해 자칫 복잡해질 수 있었던 if문 조건을 깔끔하게 정리할 수 있었다.

 

 

#include <iostream>

using namespace std;
struct robot {
	int r, c;
	int dir;
};
robot r;

int N, M;
int xy[5][2] = { {-1,0},{0,1}, {1,0}, {0,-1}, {-1,0} };
int map[51][51][2];
int cnt;
int rot;
int l_x, l_y, f_x, f_y, r_x, r_y, b_x, b_y;

bool clean_move(int x, int y){//입력된 좌표가 청소가능한가?
	if (0 <= x && x < N && 0 <= y && y < M &&
		!map[x][y][0] && !map[x][y][1]) {
		return true;
	}
	else return false;
}

void func_assgin() {
	l_x = r.r + xy[(r.dir - 1) % 4][0];//현재 방향기준 왼쪽 x
	l_y = r.c + xy[(r.dir - 1) % 4][1];//현재 방향기준 왼쪽 y
	f_x = r.r + xy[r.dir][0];//현재 방향기준 앞쪽 x
	f_y = r.c + xy[r.dir][1];//현재 방향기준 앞쪽 y
	r_x = r.r + xy[(r.dir + 1) % 4][0];//현재 방향기준 오른쪽 x
	r_y = r.c + xy[(r.dir + 1) % 4][1];//현재 방향기준 오른쪽 y
	switch (r.dir) {
	case 0:
		b_x = r.r + xy[2][0];//현재 방향기준 뒤쪽 x
		b_y = r.c + xy[2][1];//현재 방향기준 뒤쪽 y
		break;
	case 1:
		b_x = r.r + xy[3][0];//현재 방향기준 뒤쪽 x
		b_y = r.c + xy[3][1];//현재 방향기준 뒤쪽 y
		break;
	case 2:
		b_x = r.r + xy[0][0];//현재 방향기준 뒤쪽 x
		b_y = r.c + xy[0][1];//현재 방향기준 뒤쪽 y
		break;
	case 3:
		b_x = r.r + xy[1][0];//현재 방향기준 뒤쪽 x
		b_y = r.c + xy[1][1];//현재 방향기준 뒤쪽 y
		break;
	case 4:
		b_x = r.r + xy[2][0];//현재 방향기준 뒤쪽 x
		b_y = r.c + xy[2][1];//현재 방향기준 뒤쪽 y
		break;
	}
	
}

int main() {
	cin >> N >> M;
	cin >> r.r >> r.c >> r.dir;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> map[i][j][0];
		}
	}
	map[r.r][r.c][1] = 1;
	cnt++;
	while (true) {
		if (r.dir == 0) r.dir = 4;

		func_assgin();
		
		if (clean_move(l_x,l_y)) {//왼쪽 청소가 가능할 떄
			map[l_x][l_y][1] = 1;//visit
			r.r = l_x; r.c = l_y;//move
			cnt++;
			r.dir = (r.dir - 1) % 4;//방향전환
			//rot = 0;
		}
		
		else if (!clean_move(l_x, l_y) && !clean_move(r_x, r_y) && !clean_move(f_x, f_y) && !clean_move(b_x, b_y)) {//네 방향이 막혀있을/청소되어있을 때
			if (map[b_x][b_y][0]) {//뒤쪽이 막혀있을 때
				break;
			}
			else if (!map[b_x][b_y][0]) {//뒤쪽이 뚫려있을 때
				r.r = b_x; r.c = b_y;
			}
		}
		else {
			r.dir = (r.dir - 1) % 4;
		}
	}
	
	cout << cnt;

	return 0;
}

'코딩문제 풀이' 카테고리의 다른 글

14891번 톱니바퀴  (0) 2020.01.21
14888번 연산자 끼워넣기  (0) 2020.01.17
14889번 스타트와 링크  (0) 2020.01.16
백준 14502번 연구소  (0) 2020.01.14
백준 14890번 경사로  (0) 2020.01.08