백준 [13460] "구슬 탈출 2"

Kimbab1004·2024년 8월 17일
0

Algorithm

목록 보기
73/102

5달전 호기롭게 도전했다가 컴파일 되지도 않던 문제였다.

문제의 핵심은 두가지로 설정했었다.

  1. 파랑 구슬이 O에 접근해서 빠지면 안된다.
  2. 10번 이하로 빨간 구슬을 구멍을 통해 빼낼 수 없으면 -1을 출력
    횟수가 10번이 넘으면 안된다는 뜻

그럼 움직일때 마다 다음 map에 구슬의 횟수와 파랑구슬의 위치를 알고 있어야 할 것 같다.

그래서 map에는 빨강 구슬의 x,y를 알게하고 추가 map을 만들어 이곳에 파랑 구슬의 x,y 그리고 구슬을 굴린 횟수를 저장해 문제를 해결하고자 하였는데 이 부분이 불 필요한 부분이였다.

Map에 적혀있는 빨강 구슬이 파랑 구슬의 이동에 제약을 줄 수 있다는 생각이 쓸데 없이 든 탓에 문제 풀이에 오류가 있었는데 어차피 이동할때는 다음 위치가 '#' 이거나 'O' 인 경우의 조건을 설정해주면 되었기 때문에 상관이 없었다.

그리고 만약 같은 방향으로 빨강 구슬과 파랑 구슬이 움직였을때의 상황을 해결하지 못했는데 이 부분도 파랑 구슬이 이동한 값과 빨강 구슬이 이동한 값의 차이로 구할 수 있었다. 만약 파랑 구슬이 이동한 값이 더 적다면 파랑 구슬의 위치가 빨강 구슬보다 왼쪽 이동 기준 더 왼쪽에 있었다는 것이 되니 빨강 구슬은 파랑 구슬의 우측에 위치하게 된다.

오답

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

struct BEAD
{
	int blueBead_x;
	int blueBead_y;
	int times;
};


bool check[51][51] = { false };
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,-1,1 };

using namespace std;

BEAD Bead_map[50][50];

int map[50][50];

int n, m;

int result = 0;

// 1. 파랑 구슬이 O에 접근해서 빠지면 안된다.
// 2. 10번 이하로 빨간 구슬을 구멍을 통해 빼낼 수 없으면 -1을 출력
//    횟수가 10번이 넘으면 안된다는 뜻

// 그럼 움직일때 마다 다음 map에 구슬의 횟수와 파랑구슬의 위치를 알고 있어야 할듯

void solve(int red_x, int red_y) {
	queue<pair<int, int>> q;
	q.push({ red_x, red_y });
	while (!q.empty()) {

		int red_x = q.front().first;
		int red_y = q.front().second;
		
		int blue_x = Bead_map[red_x][red_y].blueBead_x;
		int blue_y = Bead_map[red_x][red_y].blueBead_y;
		
		q.pop();

		if (map[red_x][red_y] == 'O') {
			if (Bead_map[red_x][red_y].times < result) {
				result = Bead_map[red_x][red_y].times;
			}
		}

		int nred_x = red_x;
		int nred_y = red_y;

		int nblue_x = blue_x;
		int nblue_y = blue_y;

		for (int i = 0; i < 4; i++) {
			int flag = 0;
			//빨간 구슬 굴리기
			while (map[nred_x][nred_y] != '#' && map[nred_x][nred_y] != 'B') {
				if (map[nred_x][nred_y] == 'O') {
					//만약 굴리다가 정답을 발견했을 경우는 더이상 굴릴 필요가 없음
					break;
				}
				nred_x = nred_x + dx[i];
				nred_y = nred_y + dy[i];
			}
			while (map[nblue_x][nblue_y] != '#' && map[nblue_x][nblue_y] != 'R') {
				if (map[nblue_x][nblue_y] == 'O') {
					flag = 1;
					//만약 굴리다가 오답을 발견했을 경우
					break;
				}
				nblue_x = nblue_x + dx[i];
				nblue_y = nblue_y + dy[i];
			}

			//방문한 기록이 없고 파랑 구슬이 O에 들어가지 않았을때
			if (check[nred_x][nred_y] == false && flag == 0) {
				check[nred_x][nred_y] = true;
				Bead_map[nred_x][nred_y].times = Bead_map[red_x][red_y].times + 1;
				Bead_map[nred_x][nred_y].blueBead_x = nblue_x;
				Bead_map[nred_x][nred_y].blueBead_y = nblue_y;

				q.push({ nred_x,nred_y });
			}
		}

	}


	//10번 이하로 빨간 구슬을 구멍을 통해 빼낼 수 없으면 - 1을 출력
	if (result > 10) {
		cout << -1;
	}
	else {
		cout << result;
	}

}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> n >> m;

	int blue_x = 0;
	int blue_y = 0;
	int red_x = 0;
	int red_y = 0;

	for (int i = 0; i < n; i++) {
		string s;
		cin >> s;
		for (int j = 0; j < s.size(); j++) {
			map[i][j] = s[j];
			if (s[j] == 'R') {
				red_x = i;
				red_y = j;
			}
			else if (s[j] == 'B') {
				blue_x = i;
				blue_y = j;
			}
		}
	}

	Bead_map[red_x][red_y] = { blue_x, blue_y, 0 };

	solve(red_x, red_y);
	
	return 0;
}

정답

#include<iostream>
#include<queue>
#define endl "\n"
using namespace std;

struct step
{
	int Rx, Ry;
	int Bx, By;
	int Count;
};

char map[11][11];
bool visit[11][11][11][11];
int N, M;
int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,1,-1 };

void move(int& rx, int& ry, int& distance, int& i)
{
	while (map[rx + dx[i]][ry + dy[i]] != '#' && map[rx][ry] != 'O')
	{
		rx += dx[i];
		ry += dy[i];
		distance += 1;
	}
}

void BFS(int Rx, int Ry, int Bx, int By)
{
	queue<step> q;
	q.push({ Rx,Ry,Bx,By,0 });
	visit[Rx][Ry][Bx][By] = true;
	while (!q.empty())
	{
		int rx = q.front().Rx;
		int ry = q.front().Ry;
		int bx = q.front().Bx;
		int by = q.front().By;
		int count = q.front().Count;
		q.pop();

		if (count >= 10) break;

		for (int i = 0; i < 4; i++)
		{
			int nrx = rx, nry = ry, nbx = bx, nby = by;
			int rc = 0, bc = 0, ncount = count + 1;

			move(nrx, nry, rc, i);
			move(nbx, nby, bc, i);

			if (map[nbx][nby] == 'O') continue;
			if (map[nrx][nry] == 'O')
			{
				cout << ncount;
				return;
			}

			if (nrx == nbx && nry == nby)
			{
				if (rc > bc) nrx -= dx[i], nry -= dy[i];
				else nbx -= dx[i], nby -= dy[i];
			}

			if (visit[nrx][nry][nbx][nby]) continue;
			visit[nrx][nry][nbx][nby] = true;
			q.push({ nrx,nry,nbx,nby,ncount });
		}
	}
	cout << -1;
}

void Answer()
{
	cin >> N >> M;
	int Rx = 0, Ry = 0, Bx = 0, By = 0;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < M; j++)
		{
			cin >> map[i][j];
			if (map[i][j] == 'R')
			{
				Rx = i; Ry = j;
			}
			else if (map[i][j] == 'B')
			{
				Bx = i; By = j;
			}
		}
	}
	BFS(Rx, Ry, Bx, By);
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	Answer();
	return 0;
}

0개의 댓글