[백준 6087번 C/C++] 레이저 통신

 

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

 

6087번: 레이저 통신

크기가 1×1인 정사각형으로 나누어진 W×H 크기의 지도가 있다. 지도의 각 칸은 빈 칸이거나 벽이며, 두 칸은 'C'로 표시되어 있는 칸이다. 'C'로 표시되어 있는 두 칸을 레이저로 통신하기 위해서

www.acmicpc.net


 

 

해결전략

 

너비우선탐색 BFS


 

정답코드

 

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

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

int w, h;						// w: 맵의 너비, h: 맵의 높이
int answer = 987654321;			// 최소 거울 개수, 초기값은 매우 큰 값으로 설정
vector<vector<char>> v;			// 맵 정보
vector<vector<vector<int>>> ch; // 각 위치에서의 거울 개수 및 방문 여부를 저장할 3차원 벡터
int startY, startX;             // 시작 위치

struct Info{
	int y, x, dir;
};

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	queue<Info> Q;

	cin >> w >> h;
	v.resize(h, vector<char>(w));
	ch.resize(h, vector<vector<int>>(w, vector<int>(4, -1)));

	bool bStart = false; // 시작 위치가 설정되었는지 여부
	for (int y = 0; y < h; y++){
		for (int x = 0; x < w; x++) {
			cin >> v[y][x];
			if (v[y][x] == 'C' && false == bStart) {
				// 시작 위치에서 4개 방향으로 탐색 시작
				Q.push({ y, x, 0 }); // 북
				Q.push({ y, x, 1 }); // 서
				Q.push({ y, x, 2 }); // 남
				Q.push({ y, x, 3 }); // 동
				// 시작 위치에서의 거울 개수를 0으로 설정
				ch[y][x][0] = 0;
				ch[y][x][1] = 0;
				ch[y][x][2] = 0;
				ch[y][x][3] = 0;
				startY = y;
				startX = x;
				bStart = true;
			}
		}
	}

	while(!Q.empty())
	{
		int y = Q.front().y;
		int x = Q.front().x;
		int dir = Q.front().dir;
		Q.pop();

		for(int i = 0; i < 4; i++){
			int ny = y + dirY[i];
			int nx = x + dirX[i];
			int ndir = i; // 다음 방향

			if (ny < 0 || h <= ny || nx < 0 || w <= nx || v[ny][nx] == '*') continue; // 범위 밖이거나 벽인 경우
			if (ny == startY && nx == startX) continue; // 시작 위치는 지나가지 않음

			if (v[ny][nx] == 'C'){ // 목표 위치('C') 도달 시
				if (dir != ndir) // 방향을 튼 경우, 거울 개수 증가
					answer = min(answer, ch[y][x][dir] + 1);
				else // 방향을 틀지 않은 경우
					answer = min(answer, ch[y][x][dir]);
				continue;
			}

			// 아직 방문하지 않은 경우 || 더 적은 거울을 사용해 도달할 수 있는 경우
			if (ch[ny][nx][ndir] == -1 || ch[ny][nx][ndir] > ch[y][x][dir] + (dir != ndir)) {
				Q.push({ ny, nx, ndir });
				ch[ny][nx][ndir] = ch[y][x][dir] + (dir != ndir); // 방향 전환 시 거울 개수 증가
			}
		}
	}

	cout << answer;

	return 0;
}