본문 바로가기
Algorithm/DFS&BFS(완전탐색)

14503 로봇 청소기

by neohtux 2020. 7. 15.
728x90

https://www.acmicpc.net/problem/14503

 

14503번: 로봇 청소기

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

www.acmicpc.net

(풀이)

문제의 요구 사항

1. 현재 위치를 청소한다.

 

2. 현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.

  a. 왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고

     1번부터 진행한다.   

  b. 왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.

  c. 네 방향 모두 청소가 이미 되어있거나 벽인 경우에는,

     바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.

  d. 네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는

     경우에는 작동을 멈춘다.

 

(풀이) 로봇의 위치 x,y와 바라보는 방향 dir 이 필요하다. for(int i=0; i<4;++i) 문을 이용하여

4방향으로 왼쪽으로 회전을 구현. (a,b)

 

(c)"네 방향 모두 청소가 이미 되어있거나, 벽인 경우 " (for 문을 다 순회한경우)

이 경우는 로봇이 더이상 이동하지 못한경우 이다.

뒤로 후진을 하기위해 dir 변수에 +2칸 dx[] , dy[]의 인덱스로 사용 4방향이므로 mod4 모듈러

연산을 이용하여 0~3 까지 유지시켜줌.

 

후진을 할때에는 현재위치 cur_x ,cur_y에서 후진을 하여야한다.

 

(d)의 조건은 더이상 로봇이 움직이지 못하고 청소도 못하는 상황 이므로 종료.

 

bf 또는와 dfs로 구현 가능. arr의 행렬 제한은 50*50 = O(N^2)에 충분히 들어온다.

 

#include<iostream>
#include<queue>
using namespace std;

int arr[50][50];
int check[50][50];
int N, M;
queue<pair<pair<int, int>,int>> q;
void bfs();
void dfs(int x, int y, int dir);
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };
int ans = 0;
int main(void)
{
	cin >> N >> M;
	
	int pos_x, pos_y, dir;
	cin >> pos_x >> pos_y >> dir;
	q.push(make_pair(make_pair(pos_x, pos_y), dir));
	ans += 1;
	check[pos_x][pos_y] = true;

	for (int i = 0; i < N; ++i)
	{
		for (int j = 0; j < M; ++j)
			cin >> arr[i][j];
	}
	//bfs();
	dfs(pos_x, pos_y, dir);



	cout << ans << '\n';
	return 0;
}
void dfs(int x, int y, int dir)
{
	int cur_x = x;
	int cur_y = y;
	//int cur_dir = dir;
	check[cur_x][cur_y] = true;
	int next_dir = dir;
	bool isBack = false;
	for (int i = 0; i < 4; ++i) //a,b
	{
		next_dir = next_dir - 1;
		if (next_dir < 0) next_dir = 3;

		int xn = cur_x + dx[next_dir];
		int yn = cur_y + dy[next_dir];

		if (xn < 0 || xn >= N || yn < 0 || yn >= M) continue;

		if (arr[xn][yn] == 0 && check[xn][yn] == 0) 
		{
			 //a
			ans += 1;
			isBack = true;
			dfs(xn, yn, next_dir);
			break;
		}
	}

	if (isBack == false)
	{
		int new_dir = next_dir + 2;
		new_dir = new_dir % 4;

		int new_xn = cur_x + dx[new_dir];
		int new_yn = cur_y + dy[new_dir];

		if (new_xn >= 0 || new_xn < N || new_yn >= 0 || new_yn < M)
		{
			if (arr[new_xn][new_yn] != 1)
			{
				dfs(new_xn, new_yn, next_dir);
			}
		}

	}

}
void bfs()
{
	while (!q.empty())
	{
		int cur_x = q.front().first.first;
		int cur_y = q.front().first.second;
		int cur_dir = q.front().second;
		
		int next_dir = cur_dir;
		int xn = 0;
		int yn = 0;
		q.pop();
		bool isBack = false;
		for (int i = 0; i < 4; ++i)
		{
			next_dir = next_dir - 1;
			if (next_dir < 0) next_dir = 3; //a. 방향 회전.

			xn = cur_x + dx[next_dir];
			yn = cur_y + dy[next_dir]; // a. 다음칸 지정 
			
			if (xn < 0 || xn >= N || yn < 0 || yn >= M) continue;

			if (arr[xn][yn] == 0 && check[xn][yn] == false)
			{
					check[xn][yn] = true;
					q.push(make_pair(make_pair(xn, yn), next_dir)); //다음칸 전진
					isBack = true;
					break; //1번부터 진행
			}
		}
		if (isBack == false)
		{
			// c번 
				//뒤로 한칸 후진.
				int new_move = next_dir + 2;
				new_move = new_move % 4;
				xn = cur_x + dx[new_move];
				yn = cur_y + dy[new_move];
				if (xn < 0 || xn >= N || yn < 0 || yn >= M) continue;
				
				if (arr[xn][yn] != 1)
				{
					q.push(make_pair(make_pair(xn, yn), next_dir));
				}
		
		}
	}
}
300x250

'Algorithm > DFS&BFS(완전탐색)' 카테고리의 다른 글

2234 성곽  (0) 2020.07.17
17822 원판 돌리기  (0) 2020.07.15
2468 안전영역  (0) 2020.07.13
9205 맥주 마시면서 걸어가기  (0) 2020.07.13
2644 촌수 계산  (0) 2020.07.13

댓글