문제풀이/프로그래머스

[프로그래머스]경주로 건설 - JAVA

빈둥벤둥 2021. 2. 10. 14:57

[프로그래머스]경주로 건설 - JAVA

programmers.co.kr/learn/courses/30/lessons/67259

 

코딩테스트 연습 - 경주로 건설

[[0,0,0,0,0,0,0,1],[0,0,0,0,0,0,0,0],[0,0,0,0,0,1,0,0],[0,0,0,0,1,0,0,0],[0,0,0,1,0,0,0,1],[0,0,1,0,0,0,1,0],[0,1,0,0,0,1,0,0],[1,0,0,0,0,0,0,0]] 3800 [[0,0,1,0],[0,0,0,0],[0,1,0,1],[1,0,0,0]] 2100 [[0,0,0,0,0,0],[0,1,1,1,1,0],[0,0,1,0,0,0],[1,0,0,1,0,1],[

programmers.co.kr

 

풀이

최소 비용을 구하는 문제이므로 모든 경우를 다 탐색하는 dfs 보단 최단거리를 찾는 bfs가 적합하다. 

Node라는 클래스를 만들어 주어 현재 노드에 대한 x, y 좌표와 현재까지의 비용, 방향 정보를 담아 주었다.

 

여기서 중요한 점은 기존의 bfs랑은 다르게 이미 방문한 노드도 재 방문이 가능하다는 점이다. 재 방문을 했을 때의 비용이 현재 비용보다 작거나 같으면 그 방향으로 계속 가도 괜찮다는 의미이고 재 방문을 했을 때의 비용이 더 크면 그 방향으로는 더 가지 말라는 의미이므로 q에 노드를 넣어주면 안된다. 

 

방문 했는지 여부를 visited 함수를 사용해 체크하였고 첫 방문이거나, 재 방문일 경우 그 방향으로 갈 수 있는 경우라면 값을 갱신해 주었다. 

 

이 문제에서 가장 시간을 많이 빼앗긴 부분은 cost를 계산하는 부분이었다. 나는 직선으로 움직일때는 100원, 코너일때는 500원을 더해주도록 계산하였는데 문제를 자세히 읽어보면 코너를 만들때 500원이 '추가'로 든다. 즉 코너일때 비용이 기존 비용의 500원이 증가하는 것이 아니라 기존 직선 비용인 100원에 500원을 추가한 600원이 되는 것이다. 이것 때문에 계속 틀렸다... 문제를 자세히 읽자.

 

코드

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.util.*;
 
class Solution {
    
    int[] dx = {010-1};
    int[] dy = {10-10};
    boolean[][][] visited;
    int N;
    
    public int solution(int[][] board) {
        init(board.length);
        return bfs(board);
    }
    
    public void init(int n) {
        visited = new boolean[n][n][4];
        N = n;
    }
    
    public int bfs(int[][] board) {
        Queue<Node> q = new LinkedList<>();
        visited[0][0][0= visited[0][0][1= visited[0][0][2= visited[0][0][3];
        q.add(new Node(00-10));
        
        int min_cost = Integer.MAX_VALUE;
        while(!q.isEmpty()) {
            Node current = q.poll();
            if(current.x == N - 1 && current.y == N - 1) min_cost = Math.min(min_cost, current.cost);
            
            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) {
                    int next_cost = 0;
                    if(current.dir == i || current.dir == -1) next_cost = current.cost + 100//직선
                    else  next_cost = current.cost + 600//곡선
                    
                    if(!visited[nx][ny][i] || board[nx][ny] >= next_cost) {
                        q.add(new Node(nx, ny, i, next_cost));
                        visited[nx][ny][i] = true;
                        board[nx][ny] = next_cost;
                    }
                }
            }
        }
        return min_cost;
    }
    
    public class Node {
        int x, y, dir, cost;
        
        public Node(int x, int y, int dir, int cost) {
            this.x = x;
            this.y = y;
            this.dir = dir;
            this.cost = cost;
        }
    }
}
cs