본문 바로가기

온라인 코딩/탐색(Search)

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

 

 

문제

소스코드

 

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include<vector>
#include<utility>
#include<queue>
 
constexpr int STRATE_COST   = 100;
constexpr int CURVE_COST    = 600;
constexpr int BOARD_SIZE    = 26;
constexpr int MAX_COST      = 9999999;
using Direction = std::pair<intint>;
 
class CNode {
public:
    int         constructCost_;
    int         x_;
    int         y_;
    int         dir_;
};
 
int costed[BOARD_SIZE][BOARD_SIZE];
std::queue<CNode> queue;
 
int solution(std::vector<std::vector<int>> board) {
    int answer = MAX_COST;
    int goal = board.size() - 1;
    Direction direction[4= { 
        Direction{-1,0},Direction{0,-1},
        Direction{1,0}, Direction{0,1} };
 
    for (int i = 0; i < BOARD_SIZE; ++i) {
        for (int j = 0; j < BOARD_SIZE; ++j) {
            costed[i][j] = MAX_COST;
        }
    }
 
    queue.emplace(CNode{ 0,0,0,-1 });
    //BFS
    while (queue.empty() == false) {
        int x = queue.front().x_;
        int y = queue.front().y_;
        int cost = queue.front().constructCost_;
        int dir = queue.front().dir_;
 
        queue.pop();
 
        if (x == goal && y == goal) {
            if (answer >= cost) {
                answer = cost;
            }
        }
 
        //Search(Left, Right, Down, Top)
        for (int i = 0; i < 4++i) {
 
            int dx = x + direction[i].first;
            int dy = y + direction[i].second;
 
            //Safe Check
            if ( (dx >= 0 && dx < board.size()) && (dy >= 0 && dy < board.size())) {
 
                //Move Able
                if (board[dx][dy] == 0) {
 
                    int newCost;
                    
 
                    //같은 방향
                    if ((i % 2== (dir % 2|| dir == -1) {
                        newCost = cost + STRATE_COST;
                    }
                    else {
                        newCost = cost + CURVE_COST;
                    }
 
                    if (newCost <= costed[dx][dy]) {
                        costed[dx][dy] = newCost;
                        queue.emplace(CNode{ newCost,dx,dy,i });
                    }
                }
            }
        }
    }
    return answer;
}

후기

이 문제를 해결하기 위한 키워드는 BFS 혹은 다익스트라이다.

다익스트라를 이용해서 풀 수 있지만 여기서는 BFS를 이용해서 풀었다.

 

BFS/DFS 나 다익스트라 A*까지 구현해봐서 비교적 쉬울거라고 예상했지만 시간이 좀 걸렸던 문제였다.

시간이 걸린이유는 탐색알고리즘부분이 아니라 코너 부분을 어떻게 해결할 것인가 부분에서 시간이 꽤걸렸다.

 

처음에는 old_x, old_y 와 같이 탐색 전 노드와 비교해서 코너 여부를 판단했지만 쉽지 않아서 다른분들이 풀었던 방식을 조금 참조했는데 대부분 방향을 가지고 탐색을 시도하는 방식으로 풀어서 나도 그러한 방식으로 풀었다.

 

0(왼쪽), 1(아래), 2(왼쪽), 3(위) 이런식으로 방향이 있을 때 i%2와 dir%2가 같으면 같은 수평방향이며 다르면 수직이기 때문에 코너 가중치를 계산하도록 하였다. -1은 처음에는 직선만 하는 경우를 예외처리해서 넣은 경우이다.

 

 

처음 위치(원)에서 왼, 오른, 아래, 위 방향으로 (100+100)100씩 가중치를 더하고 여기서 화살표는 방향을 나타낸다.

 

그 다음 원에서 위쪽 방향으로 이동 후 다시 탐색을 시작할 때 위 방향이 아닌 왼쪽과 오른쪽은 (200+600)의 가중치를 더해서 Queue에 넣는 것을 확인할 수 있다.

 

문제에서 나오는 코너의 가중치는 500인대 600을 더하는 이유는 코너에 직선이 추가적으로 들어가기 때문이다.

 

 

* 만약 테스트 케이스 21,22번이 틀린다면 MAX_COST 값을 늘려보는걸 추천한다.

 

출처 및 레퍼런스

문제 링크: https://programmers.co.kr/learn/courses/30/lessons/67259

 

 

 

 

'온라인 코딩 > 탐색(Search)' 카테고리의 다른 글

[백준] 2018번 수들의 합 5  (0) 2020.10.05
[프로그래머스] 네트워크  (0) 2020.10.01
[백준] 1697번 숨바꼭질  (0) 2020.09.10
[백준] 6603번 로또  (0) 2020.07.20
[구름 IDE] 비타알고 시즌2 졸업(★3)  (0) 2020.07.02