오늘은 여기까지
[프로그래머스] 경주로 건설 - Java 자바 본문
https://school.programmers.co.kr/learn/courses/30/lessons/67259
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
개념: bfs, 그래프 탐색
문제
제공된 경주로 설계 도면에 따르면 경주로 부지는 `N x N` 크기의 정사각형 격자 형태이며 각 격자는 `1 x 1` 크기입니다.
설계 도면에는 각 격자의 칸은 `0` 또는 `1` 로 채워져 있으며, `0`은 칸이 비어 있음을 `1`은 해당 칸이 벽으로 채워져 있음을 나타냅니다.
경주로의 출발점은 (0, 0) 칸(좌측 상단)이며, 도착점은 (N-1, N-1) 칸(우측 하단)입니다. 죠르디는 출발점인 (0, 0) 칸에서 출발한 자동차가 도착점인 (N-1, N-1) 칸까지 무사히 도달할 수 있게 중간에 끊기지 않도록 경주로를 건설해야 합니다.
경주로는 상, 하, 좌, 우로 인접한 두 빈 칸을 연결하여 건설할 수 있으며, 벽이 있는 칸에는 경주로를 건설할 수 없습니다.
이때, 인접한 두 빈 칸을 상하 또는 좌우로 연결한 경주로를 `직선 도로` 라고 합니다.
또한 두 `직선 도로`가 서로 직각으로 만나는 지점을 `코너` 라고 부릅니다.
건설 비용을 계산해 보니 `직선 도로` 하나를 만들 때는 100원이 소요되며, `코너`를 하나 만들 때는 500원이 추가로 듭니다.
죠르디는 견적서 작성을 위해 경주로를 건설하는 데 필요한 최소 비용을 계산해야 합니다.
예를 들어, 그림은 직선 도로 6개와 코너 4개로 구성된 임의의 경주로 예시이며, 건설 비용은 6 x 100 + 4 x 500 = 2600원 입니다.
풀이
전체코드
import java.util.*;
class Solution {
static int n, answer;
static int[] dx = {1, -1, 0, 0};
static int[] dy = {0, 0, 1, -1};
static int[][][] visited; // [x][y][방향]
static class Car implements Comparable<Car> {
int x;
int y;
int cost;
int dir;
public Car(int x, int y, int cost, int dir) {
this.x = x;
this.y = y;
this.cost = cost;
this.dir = dir;
}
@Override
public int compareTo(Car other) {
return this.cost - other.cost;
}
}
public static void bfs(int[][] board) {
PriorityQueue<Car> pq = new PriorityQueue<>();
pq.add(new Car(0, 0, 0, -1)); // 초기 방향 -1
// 모든 위치의 모든 방향에 대해 최대값으로 초기화
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
for(int k = 0; k < 4; k++) {
visited[i][j][k] = Integer.MAX_VALUE;
}
}
}
while (!pq.isEmpty()) {
Car current = pq.poll();
if (current.x == n - 1 && current.y == n - 1) {
answer = Math.min(answer, current.cost);
continue;
}
for (int i = 0; i < 4; i++) {
int nx = current.x + dx[i];
int ny = current.y + dy[i];
if (nx < 0 || ny < 0 || nx >= n || ny >= n || board[nx][ny] == 1) {
continue;
}
// 비용 계산
int newCost = current.cost;
if (current.dir == -1) { // 시작점
newCost += 100;
} else if (current.dir == i) { // 직진
newCost += 100;
} else { // 코너
newCost += 600;
}
// 같은 위치, 같은 방향으로 도착했을 때 비용이 더 작은 경우에만 갱신
if (visited[nx][ny][i] > newCost) {
visited[nx][ny][i] = newCost;
pq.add(new Car(nx, ny, newCost, i));
}
}
}
}
public int solution(int[][] board) {
answer = Integer.MAX_VALUE;
n = board.length;
visited = new int[n][n][4]; // 3차원 배열
bfs(board);
return answer;
}
}
`visited` 배열에서도 방향을 고려해야 하는 이유:
- 같은 위치라도 도착하는 방향에 따라 이후의 최소 비용이 달라질 수 있기 때문
- Car 객체의 `dir` 외 별개로, 각 위치에 각 방향으로 도착했을 때의 최소 비용을 따로 관리한다.
'Problem Solving' 카테고리의 다른 글
[백준/7576] 토마토 - Java 자바 (1) | 2024.12.13 |
---|---|
[프로그래머스] 전력망을 둘로 나누기 - Java 자바 (0) | 2024.11.27 |
[프로그래머스] 미로 탈출 - Java 자바 (2) | 2024.11.22 |
[백준/12851] 숨바꼭질 2 - Java 자바 (0) | 2024.11.21 |
[swea/4008] 숫자 만들기 - Java 자바 (0) | 2024.11.19 |