티스토리 뷰

728x90

문제

많은 공장에서 로봇이 이용되고 있다. 우리 월드 공장의 로봇은 바라보는 방향으로 궤도를 따라 움직이며, 움직이는 방향은 동, 서, 남, 북 가운데 하나이다. 로봇의 이동을 제어하는 명령어는 다음과 같이 두 가지이다.

  • 명령 1. Go k: k는 1, 2 또는 3일 수 있다. 현재 향하고 있는 방향으로 k칸만큼 움직인다.
  • 명령 2. Turn dir: dir은 left 또는 right 이며, 각각 왼쪽 또는 오른쪽으로 90° 회전한다.

공장 내 궤도가 설치되어 있는 상태가 아래와 같이 0과 1로 이루어진 직사각형 모양으로 로봇에게 입력된다. 0은 궤도가 깔려 있어 로봇이 갈 수 있는 지점이고, 1은 궤도가 없어 로봇이 갈 수 없는 지점이다. 로봇이 (4, 2) 지점에서 남쪽을 향하고 있을 때,  이 로봇을 (2, 4) 지점에서 동쪽으로 향하도록 이동시키는 것은 아래와 같이 9번의 명령으로 가능하다.

로봇의 현재 위치와 바라보는 방향이 주어졌을 때, 로봇을 원하는 위치로 이동시키고, 원하는 방향으로 바라보도록 하는데 최소 몇 번의 명령이 필요한지 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 공장 내 궤도 설치 상태를 나타내는 직사각형의 세로 길이 M과 가로길이 N이 빈칸을 사이에 두고 주어진다. 이때 M과 N은 둘 다 100 이하의 자연수이다. 이어 M줄에 걸쳐 한 줄에 N개씩 각 지점의 궤도 설치 상태를 나타내는 숫자 0 또는 1이 빈칸을 사이에 두고 주어진다. 다음 줄에는 로봇의 출발 지점의 위치 (행과 열의 번호)와 바라보는 방향이 빈칸을 사이에 두고 주어진다. 마지막 줄에는 로봇의 도착 지점의 위치 (행과 열의 번호)와 바라보는 방향이 빈칸을 사이에 두고 주어진다. 방향은 동쪽이 1, 서쪽이 2, 남쪽이 3, 북쪽이 4로 주어진다. 출발지점에서 도착지점까지는 항상 이동이 가능하다.

 

출력

첫째 줄에 로봇을 도착 지점에 원하는 방향으로 이동시키는데 필요한 최소 명령 횟수를 출력한다.

 

코드

#include <iostream>
#include <cstring>
#include <queue>

#define	EAST	1
#define	WEST	2
#define	SOUTH	3
#define	NORTH	4

#define	L	4
#define	R	5

using namespace std;

struct pos
{
	int r;
	int c;
	int d;
};

int M;
int N;
int board[101][101];
pos src, dst;

// 범위 안인지 확인 (1, 1) ~ (M, N)
bool in_range(pos p)
{
	if (p.r <= 0 || p.r > M || p.c <= 0 || p.c > N)
		return false;
	return true;
}

// 향하는 방향으로 k칸 이동
pos go(pos curr, int k)
{
	int i;
	int dr[] = {0, 0, 0, 1, -1};	// E-W-S-N
	int dc[] = {0, 1, -1, 0, 0};	// E-W-S-N
	pos next = curr;

	for (i = 0; i < k; i++)
	{
		// 향하는 방향으로 1칸 이동함
		next.r += dr[next.d];
		next.c += dc[next.d];
		// 범위 밖이거나 벽이면 이동하지 않음
		if (!in_range(next) || board[next.r][next.c])
			return curr;
	}
	return next;
}

// 주어진 방향으로 90도 회전
pos turn(pos curr, int dir)
{
	int i;
	int d[] = {NORTH, EAST, SOUTH, WEST};
	pos next = curr;

	// 현재 방향에 대한 인덱스를 찾음
	for (i = 0; i < 4; i++)
		if (d[i] == next.d)
			break;
	// 주어진 방향으로 90도 회전함
	if (dir == L && --i < 0)
		i = 3;
	else if (dir == R && ++i > 3)
		i = 0;
	// 회전한 방향을 저장함
	next.d = d[i];
	return next;
}

// 목적지로 가기 위한 최소 명령의 수를 구함
int bfs()
{
	queue<pos> q;
	pos curr, next;
	bool visit[101][101][5];
	int i, s, size, cnt = 0;

	memset(visit, false, sizeof(visit));
	curr = src;
	visit[curr.r][curr.c][curr.d] = true;
	q.push(curr);
	while (!q.empty())
	{
		size = q.size();
		for (s = 0; s < size; s++)
		{
			curr = q.front();
			q.pop();
			// 목적지이면 리턴
			if (curr.r == dst.r && curr.c == dst.c && curr.d == dst.d)
				return cnt;
			// 가능한 연산을 적용하여 다음 좌표를 구함
			// 범위 밖이거나 벽이거나 방문했다면 패스
			// 조건을 만족하면 방문 표시하고 큐에 삽입
			for (i = 1; i <= 5; i++)
			{
				if (i <= 3)
					next = go(curr, i);
				else
					next = turn(curr, i);
				if (!in_range(next))
					continue;
				if (board[next.r][next.c])
					continue;
				if (visit[next.r][next.c][next.d])
					continue;
				visit[next.r][next.c][next.d] = true;
				q.push(next);
			}
		}
		cnt++;
	}
	return -1;
}

int main()
{
	int i, j;

	cin >> M >> N;
	for (i = 1; i <= M; i++)
	{
		for (j = 1; j <= N; j++)
		{
			cin >> board[i][j];
		}
	}
	cin >> src.r >> src.c >> src.d;
	cin >> dst.r >> dst.c >> dst.d;
	cout << bfs() << endl;
	return 0;
}

 

링크

 

1726번: 로봇

많은 공장에서 로봇이 이용되고 있다. 우리 월드 공장의 로봇은 바라보는 방향으로 궤도를 따라 움직이며, 움직이는 방향은 동, 서, 남, 북 가운데 하나이다. 로봇의 이동을 제어하는 명령어는

www.acmicpc.net

 

inbdni/Baekjoon

Contribute to inbdni/Baekjoon development by creating an account on GitHub.

github.com

 

728x90
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
공지사항
링크
Total
Today
Yesterday