티스토리 뷰
캐릭터가 상대방 진영까지 가는데 걸리는 최단거리를 구하는 문제
제목 보고 그래프 문제인 줄 알고 시작했는데 알고보니 bfs 문제였다.
하지만 아직 bfs도 숙련되지 못했기 때문에 푸는데 오래 걸렸다...
문제의 조건
1. 게임 맵에서 벽과 길을 표시한 2차원 배열 maps가 주어짐
2. maps에서 0은 벽이라서 지나갈 수 없고 1은 길이라서 지나갈 수 있다.
3. 캐릭터의 초기 위치는 항상 [0,0] 이고 상대방 진영 위치는 항상 맵의 우측 하단이다.
즉 상대방 진영 위치는 n x m 크기를 가진 maps 배열 상에서 [n-1, m-1] 이다.
풀이 과정
1. bfs로 이동할 수 있는 다음 칸을 탐색하면서 다음 칸까지의 최단 거리를 계산한다.
=> bfs로 이동할 다음 칸을 저장할 queue 필요
queue<pair<int, int>> queue;
=> 맵에서 각 칸 까지의 이동거리를 저장할 새로운 2차원 배열이 필요
시작점에서부터 각 칸까지의 이동거리를 위와 같이 계산할 수 있도록 코드를 짜야 함
dist라는 이름을 가진 거리를 계산할 2차원 배열을 게임 맵과 같은 크기로 하나 만든다.
int n = maps.size(); //맵의 세로 길이
int m = maps[0].size(); //맵의 가로 길이
vector<vector<int>> dist(n, vector<int>(m, 0));
dist 배열의 모든 원소는 0으로 초기화 함
bfs로 다음에 이동할 수 있는 칸을 탐색하면서 해당 칸에 이동거리를 저장하면 된다.
2. 캐릭터가 다음으로 이동할 위치를 탐색할 때 현재위치를 기준으로 상하좌우 방향을 검사하기 때문에
이전에 방문했던 위치에 다시 방문할 수 있다.
이전에 방문했던 위치에는 다시 방문하지 않도록 방문한 위치를 저장할 배열이 필요하다.
처음에는 set<pair<int, int>>으로 방문 좌표를 저장하는 방식으로 했는데
set에서 방문 좌표를 확인하는 과정에서 시간이 오래 걸린건지 시간초과 나고 몇몇 테스트 케이스는 통과하지 못해서
dist 배열처럼 게임 맵과 같은 크기의 bool 배열을 만들어서 체크했다.
vector<vector<bool>> visited(n, vector<bool>(m, false));
이렇게 만들어서 사용
캐릭터가 visited[n-1][m-1] 위치에 방문했다면 해당 인덱스 값을 true일 테니 최단 거리를 리턴하고
visited[n-1][m-1] = false면 방문하지 못한 것이니 -1을 리턴하면 된다.
#include<vector>
#include <queue>
using namespace std;
int solution(vector<vector<int>> maps)
{
int n = maps.size();
int m = maps[0].size(); //맵의 가로, 세로 길이
vector<vector<int>> dir;
dir.emplace_back(vector<int>{0,1});
dir.emplace_back(vector<int>{0,-1});
dir.emplace_back(vector<int>{1,0});
dir.emplace_back(vector<int>{-1,0}); //기준 위치 상하좌우 탐색방향
int answer = 0;
queue<pair<int, int>> queue; //pair.first = x 좌표, pair.second = y 좌표
vector<vector<bool>> visited(n, vector<bool>(m, false));
vector<vector<int>> dist(n, vector<int>(m, 0));
visited[0][0] = true; //초기 위치는 방문했으니까 true로 시작
dist[0][0] = 1; //초기 위치까지의 이동거리는 1부터 시작함
queue.emplace(make_pair(0, 0)); //캐릭터 초기 위치 0,0부터 시작
while (!queue.empty())
{
int x = queue.front().first;
int y = queue.front().second;
queue.pop();
//현위치 기준으로 상하좌우 방향으로 이동할 수 있는 칸을 탐색하는데
for (int i = 0; 4 > i; i++)
{
pair<int, int> nextPos = make_pair(x + dir[i][1], y + dir[i][0]);
if (0 <= nextPos.first && m > nextPos.first //맵을 벗어나지 않으면서
&& 0 <= nextPos.second && n > nextPos.second
&& 1 == maps[nextPos.second][nextPos.first] //해당 위치가 길(1)이고
&& !visited[nextPos.second][nextPos.first]) //방문한 적 없으면
{
//방문했다는 표시를 하고
visited[nextPos.second][nextPos.first] = true;
//다음 탐색의 기준위치로 설정해야 하니까 방문 예정 큐에 저장
queue.emplace(nextPos);
//해당 위치까지의 누적 거리를 저장한다.
//1칸씩 이동하니까 현재 dist 배열에 저장된 값에 +1 해주면 됨
dist[nextPos.second][nextPos.first] = dist[y][x] + 1;
}
}
}
if (!visited[n-1][m-1]) //상대방 진영에 벽에 막혀서 못 갔으면 해당 위치는 false일 것임
answer = -1;
else //true라면 상대방 진영에 갔다는 뜻이니까 위에서 저장해 온 최단거리 리턴
answer = dist[n-1][m-1];
return answer;
}
'알고리즘 문제 풀이' 카테고리의 다른 글
[JAVA] 백준 2588번 곱셈 풀이 (0) | 2021.12.31 |
---|---|
[C++] 프로그래머스 순위 풀이(플로이드-워셜 알고리즘) (0) | 2021.10.19 |
[C++] 프로그래머스 신규 아이디 추천 풀이 (0) | 2021.10.17 |
[C++] 프로그래머스 로또의 최고 순위와 최저 순위 풀이 (0) | 2021.10.17 |
[C++] 프로그래머스 디스크 컨트롤러 풀이 (0) | 2021.10.16 |
- Total
- Today
- Yesterday
- 코딩공부
- 프로그래머스
- hackerrank
- 해커랭크
- 캐나다생활
- 기초
- 애플
- 깊이우선탐색
- 백준
- c언어
- greedy
- DFS
- 아이패드
- 캐나다
- 영어공부
- 컴퓨터공부
- dp
- 컴퓨터사이언스
- 컴퓨터
- c++
- 다이나믹프로그래밍
- C언어기초
- 스위프트플레이그라운드
- 그리디
- 하드웨어
- 너비우선탐색
- 알고리즘
- 프로그래밍
- BFS
- 문제풀이
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |