리뷰
https://www.acmicpc.net/problem/2151
최소한의 거울을 설치하여 한쪽 문에서 다른 문으로 이동하는 경로를 찾는 문제
전역 변수
- n : 맵의 가로/세로 길이를 저장할 변수
- sx, sy : 탐색을 시작할 문의 좌표를 저장할 변수
- ex, ey : 도착할 문의 좌표를 저장할 변수
- lst : 맵 정보를 저장할 문자열 배열
- bool : 설치한 거울의 개수로 방문 정보를 체크할 배열
- Pos : 시뮬레이션 시 사용할 현재 좌표 x, y, 현재 방향 d, 설치한 거울의 수 c를 정의할 구조체, c를 기준으로 오름차순 정렬해 준다.
- dx, dy : 4방향 탐색을 위한 방향 배열
함수
1. dijkstra
int dijkstra()
다익스트라를 사용해 출발 문에서 도착 문까지 이동할 때 최소 설치 거울의 개수를 구하는 함수
- Pos 타입의 우선순위 큐 pq를 초기화 한다.
- 초기 좌표에서 4방향 정보를 담고, 거울 설치 개수 0으로 총 4개를 push해준다.
- 거울 설치 횟수가 0이면서 시작 좌표인 지점에 방문 처리를 진행해 준다.
- pq가 빌 때 까지 while 루프를 수행하고, 매 루프마다 요소를 한 개씩 꺼내어 준다.
- 기저 조건으로 만약 문에 도착한 경우 현재 거울 설치 개수를 리턴해 준다.
- 현재 방향으로 쭉 탐색하며 맵의 범위 안에 있으며 벽을 만나지 않았고 방문 하지 않았다면 이동을 진행한다.
- 이동한 위치가 거울 설치 가능한 지역이라면 설치 개수를 늘려 해당 위치를 방문 처리해 준다.
- 이동한 좌표와 진행 방향에서 좌우 방향, 설치 개수를 늘린 구조체를 pq에 push해준다.
- 만약 문을 만난 경우 방문 처리 후 pq에 삽입해 준 후 continue 처리해 준다.
문제풀이
- n값을 입력 받고, 변수 idx를 0으로 초기화 해준다.
- n * n크기의 맵 정보를 입력 받고, 문이 입력으로 들어온 경우 좌표를 저장해 준다.
- 만약 idx가 0이라면 sx, sy에 시작 문의 위치를 저장하고 idx를 1만큼 증가시켜 준다.
- idx가 0이 아니라면 ex, ey에 도착 문의 위치를 저장해 준다.
- dijkstra 함수를 호출하고 리턴 받은 값을 출력해 준다.
트러블 슈팅
- 초기엔 백트래킹 + BFS로 탐색을 진행하였으나, 거울의 개수를 문제에서 알려주지 않아 시간 초과를 받았다.
- 이후 다익스트라 로직을 구현하고 제출을 하였으나 v배열에서 거울의 개수를 50개로 잡았더니 Fail을 받았다.
- v배열의 크기를 거울이 나올 수 있는 최대값으로 설정하여 제출하였더니 AC를 받았다.
참고 사항
- v배열을 2500 * 50 * 50으로 설정하니 제출을 받은걸 보아 거울의 개수가 매우 많은 경우도 존재하는 것 같다.
- 논리형 배열로 초기화 한다면 메모리 면에서도 크게 영향을 받지 않는 것 같다.
정답 코드
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
int n, sx, sy, ex, ey;
string lst[50];
bool v[2500][50][50];
struct Pos {
int x, y, d, c;
bool operator<(const Pos& other) const {
return c > other.c;
}
};
int dx[] = { 1, 0, -1, 0 };
int dy[] = { 0, 1, 0, -1 };
void print(int x, int y) {
cout << "\n";
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == x && j == y) cout << "@";
else cout << lst[i][j];
}
cout << "\n";
}
}
int dijkstra() {
priority_queue<Pos> pq;
for (int i = 0; i < 4; ++i) pq.push({ sx, sy, i, 0 });
v[0][sx][sy] = true;
while (!pq.empty()) {
Pos pos = pq.top(); pq.pop();
int cx = pos.x, cy = pos.y, cd = pos.d, cc = pos.c;
if (cx == ex && cy == ey) return cc;
int nx = cx + dx[cd], ny = cy + dy[cd];
while (0 <= nx && nx < n && 0 <= ny && ny < n && lst[nx][ny] != '*' && !v[cc][nx][ny]) {
if (lst[nx][ny] == '!') {
v[cc + 1][nx][ny] = true;
pq.push({ nx, ny, (cd + 1) % 4, cc + 1 });
pq.push({ nx, ny, (cd + 3) % 4, cc + 1 });
}
else if (lst[nx][ny] == '#') {
v[cc][nx][ny] = true;
pq.push({ nx, ny, -1, cc });
continue;
}
nx += dx[cd];
ny += dy[cd];
}
}
return -1;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
int idx = 0;
for (int i = 0; i < n; ++i) {
cin >> lst[i];
for (int j = 0; j < n; ++j) {
if (lst[i][j] == '#') {
if (!idx) {
sx = i, sy = j;
idx++;
}
else ex = i, ey = j;
}
}
}
cout << dijkstra();
}
728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
[S3] 백준 2149번 암호 해독 C++ 문자열, 정렬 (0) | 2025.02.26 |
---|---|
[G4] 백준 14267번 회사 문화 1 C++ 세그먼트 트리, 느리게 갱신되는 세그먼트 트리, 오일러 경로 테크닉 (0) | 2025.02.26 |
[G5] 백준 17396번 백도어 C++ 다익스트라 (0) | 2025.02.24 |
[G5] 백준 2866번 문자열 잘라내기 C++ 해시 맵, 매개 변수 탐색 (0) | 2025.02.24 |
[G3] 백준 1520번 내리막 길 C++ 다이나믹 프로그래밍, 깊이 우선 탐색 (0) | 2025.02.24 |