더보기
BFS는 노드와 노드 간 최단 거리를 계산하기 위해서 사용합니다.
문제에서는 시작 노드에서 시작해 레버 노드를 경유하고 최종적으로 도착 노드에 도달해야합니다.
BFS를 연속 실행하고 연속된 BFS 결과를 합산하는 것으로 결과를 도출합니다.
Step 1: 노드를 표현하는 클래스
길 찾기를 위한 경로는 2차원 좌표계-이중 배열로 제공됩니다. 이를 표현하고 저장하기 위한 Node 클래스를 생성합니다.
public class Node
{
public int x, y;
public int cost;
public Node(int x, int y, int cost)
{
this.x = x;
this.y = y;
this.cost = cost;
}
}
코드 | 비고 | |
2차원 좌표계 위의 |
||
Step 2: BFS 구현
2차원 좌표계에서 시작 지점 bx, by에서 출발해 도착 지점 gx, gy에 도달하는 최단 거리를 계산합니다.
이때 도착 지점에 도달하면 해당 노드까지의 거리(cost)를 리턴하고, 도착하지 못하면 -1을 리턴합니다.
public int bfs(String[] maps, int bx, int by, int gx, int gy)
{
int[] dx = { 0, 1, 0, -1 };
int[] dy = { -1, 0, 1, 0 };
int h = maps.length;
int w = maps[0].length();
int x = bx, y = by;
boolean[][] visited = new boolean[h][w];
Queue<Node> q = new LinkedList<>();
q.offer(new Node(x, y, 0));
visited[y][x] = true;
while (!q.isEmpty())
{
Node n = q.poll();
if (n.x == gx && n.y == gy)
return n.cost;
for (int i = 0; i < 4; ++i)
{
int nx = n.x + dx[i];
int ny = n.y + dy[i];
if (nx < 0 || ny < 0 || nx >= w || ny >= h)
continue;
char[] s = maps[ny].toCharArray();
char c = s[nx];
if (!visited[ny][nx] && 'X' != c)
{
visited[ny][nx] = true;
q.offer(new Node(nx, ny, n.cost + 1));
}
}
}
return -1;
}
코드 | 비고 | |
현재 |
||
목표 좌표에 도달하면 |
||
문제의 규칙에 따라서 |
||
BFS가 종료되었으나 |
Step 3: 두 번의 BFS 실행으로 세 개의 노드를 연결
문제에서는 시작 노드에서 시작해 레버 노드를 경유하고 최종적으로 도착 노드에 도달해야합니다.
두 개의 노드를 잇는 경로에서 3자 노드를 반드시 경유하는 길찾기는 다음과 같이 단순화 할 수 있습니다.
더보기
시작 노드에서 3자 노드까지의 최단 거리를 계산합니다.
경유를 위한 3자 노드에서 종료 노드까지의 최단 거리를 계산합니다.
그리고나서 두 개의 최단 거리를 합산합니다.
우선 좌표계로 제공된 이중 배열 maps를 순회하면서 각 노드의 좌표를 구합니다.
그다음 두 번의 BFS를 실행하여 문제의 결과를 도출합니다.
public int solution(String[] maps)
{
int sx = 0, sy = 0, lx = 0, ly = 0, ex = 0, ey = 0;
for (int y = 0; y < maps.length; ++y)
{
char[] s = maps[y].toCharArray();
for (int x = 0; x < s.length; ++x)
{
char c = s[x];
switch (c)
{
case 'S' -> {
sx = x;
sy = y;
}
case 'L' -> {
lx = x;
ly = y;
}
case 'E' -> {
ex = x;
ey = y;
}
}
}
}
int toL = bfs(maps, sx, sy, lx, ly);
if (toL <= -1) return -1;
int toE = bfs(maps, lx, ly, ex, ey);
if (toE <= -1) return -1;
return toL + toE;
}
코드 | 비고 | |
만약 경로를 찾지 못하면 |
||
만약 경로를 찾지 못하면 |
||
두 번의 BFS 결과를 합산하여 리턴합니다. |
Step 4: 전체 코드
각 단계별로 구성된 전체 코드는 다음을 참고합니다.
import java.util.*;
public class Solution
{
public class Node
{
public int x, y;
public int cost;
public Node(int x, int y, int cost)
{
this.x = x;
this.y = y;
this.cost = cost;
}
}
public int solution(String[] maps) {
int sx = 0, sy = 0, lx = 0, ly = 0, ex = 0, ey = 0;
for (int y = 0; y < maps.length; ++y)
{
char[] s = maps[y].toCharArray();
for (int x = 0; x < s.length; ++x)
{
char c = s[x];
switch (c)
{
case 'S' -> {
sx = x;
sy = y;
}
case 'L' -> {
lx = x;
ly = y;
}
case 'E' -> {
ex = x;
ey = y;
}
}
}
}
int toL = bfs(maps, sx, sy, lx, ly);
if (toL <= -1) return -1;
int toE = bfs(maps, lx, ly, ex, ey);
if (toE <= -1) return -1;
return toL + toE;
}
public int bfs(String[] maps, int bx, int by, int gx, int gy)
{
int[] dx = { 0, 1, 0, -1 };
int[] dy = { -1, 0, 1, 0 };
int h = maps.length;
int w = maps[0].length();
int x = bx, y = by;
boolean[][] visited = new boolean[h][w];
Queue<Node> q = new LinkedList<>();
q.offer(new Node(x, y, 0));
visited[y][x] = true;
while (!q.isEmpty())
{
Node n = q.poll();
if (n.x == gx && n.y == gy)
return n.cost;
for (int i = 0; i < 4; ++i)
{
int nx = n.x + dx[i];
int ny = n.y + dy[i];
if (nx < 0 || ny < 0 || nx >= w || ny >= h)
continue;
char[] s = maps[ny].toCharArray();
char c = s[nx];
if (!visited[ny][nx] && 'X' != c)
{
visited[ny][nx] = true;
q.offer(new Node(nx, ny, n.cost + 1));
}
}
}
return -1;
}
}
'Algorithm > Programmers' 카테고리의 다른 글
Level 2: 2023 KAKAO BLIND RECRUITMENT - 이모티콘 할인 행사, 중복 순열 (0) | 2023.12.27 |
---|---|
Level 2: 무인도 여행, BFS를 사용한 2차원 좌표계에서 고립된 영역 탐색 (0) | 2023.12.20 |
Level 2: 뒤에 있는 큰 수 찾기, Stack 자료 구조를 사용한 풀이 (0) | 2023.12.08 |
Level 2: 요격 시스템, 하나의 축에서 최소한의 교집합 구하기 (0) | 2023.12.07 |
Level 1: 카드 뭉치, 배열의 큐잉(Queueing) (0) | 2023.12.06 |