1 분 소요

두 동전 (백준 Gold 4)

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

N x M 의 맵 데이터가 주어지고
동전이 2개 주어졌을때
동전을 이동시켜 1개만 맵 밖으로 탈출하는 최소 횟수를 구하기

  • 동전은 겹칠 수 있음
  • 상 하 좌 우 1칸씩 이동
  • 10번이 넘어가거나, 탈출이 불가능한 경우 -1 출력
  • 움직이려는 방향에 벽이 있는 경우는 움직이지 않음

풀이 방법

각각의 요소가 ‘동일’하게 움직이므로
2개의 요소를 같이 Queue를 통해 움직이면 구할 수 있는 문제

  • 동전이 동시에 나가는 경우는 포함하지 않음

제출 코드

#include<iostream>
#include<vector>
#include<string>
#include<queue>

using namespace std;

const int dirY[4] = { 0,-1,0,1 };
const int dirX[4] = { -1,0,1,0 };

int n, m;

struct pos
{
	int y, x;
};

struct QIn
{
	pos c1;
	pos c2;
	int cost;
};

int bfs(vector<string>& t, pos& c1,pos& c2)
{
	queue<QIn> q;
	q.push({ c1, c2,0 });

	while (q.empty() == false)
	{
		pos nowC1 = q.front().c1;
		pos nowC2 = q.front().c2;
		int cost = q.front().cost;
		q.pop();

		for (int i = 0; i < 4; i++)
		{
			pos nC1 = {nowC1.y + dirY[i],nowC1.x + dirX[i]};
			pos nC2 = {nowC2.y + dirY[i],nowC2.x + dirX[i]};
			int nCost = cost + 1;

			if (nCost > 10)
				continue;

			if (nC1.y < 0 || nC1.y >= n ||
				nC1.x < 0 || nC1.x >= m ||
				nC2.y < 0 || nC2.y >= n ||
				nC2.x < 0 || nC2.x >= m)
			{
				// 둘다 나간 경우
				if ((nC1.y < 0 || nC1.y >= n ||
					nC1.x < 0 || nC1.x >= m) &&
					(nC2.y < 0 || nC2.y >= n ||
						nC2.x < 0 || nC2.x >= m))
					continue;

				return nCost;
			}

			if (t[nC1.y][nC1.x] == '#')
			{
				nC1 = nowC1;
			}

			if (t[nC2.y][nC2.x] == '#')
			{
				nC2 = nowC2;
			}

			q.push({ nC1,nC2,nCost });
		}
	}

	return -1;
}

int main()
{
	cin >> n >> m;
	vector<string> t(n);
	
	bool bC1 = false;
	pos c1, c2;

	for (int i = 0; i < n; i++)
	{
		cin >> t[i];
		for (int j = 0; j < m; j++)
		{
			if (t[i][j] == 'o')
			{
				if (bC1 == false)
				{
					c1.y = i;
					c1.x = j;
					bC1 = true;
				}
				else
				{
					c2.y = i;
					c2.x = j;
				}
			}
		}
	}

	cout << bfs(t, c1, c2);

	return 0;
}

결과

Image

원래는 visit 배열을 각각 만들까 하다가
10번 제한이 있기에 간단히 구현을 하였다

댓글남기기