프로그래머스

[프로그래머스, c++] 여행경로(DFS)

전두선 2021. 3. 28. 14:22
[프로그래머스, c++] 여행경로(DFS)
난이도 Level 3
분류 DFS/BFS
programmers.co.kr/learn/courses/30/lessons/43164

 

문제 및 입/출력

주어진 항공권을 모두 이용하여 여행경로를 짜려고 합니다. 항상 "ICN" 공항에서 출발합니다. 항공권 정보가 담긴 2차원 배열 tickets가 매개변수로 주어질 때, 방문하는 공항 경로를 배열에 담아 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 모든 공항은 알파벳 대문자 3글자로 이루어집니다.
  • 주어진 공항 수는 3개 이상 10,000개 이하입니다.
  • tickets의 각 행 [a, b]는 a 공항에서 b 공항으로 가는 항공권이 있다는 의미입니다.
  • 주어진 항공권은 모두 사용해야 합니다.
  • 만일 가능한 경로가 2개 이상일 경우 알파벳 순서가 앞서는 경로를 return 합니다.
  • 모든 도시를 방문할 수 없는 경우는 주어지지 않습니다.

 

입출력 예

tickets return
[["ICN", "JFK"], ["HND", "IAD"], ["JFK", "HND"]] ["ICN", "JFK", "HND", "IAD"]
[["ICN", "SFO"], ["ICN", "ATL"], ["SFO", "ATL"], ["ATL", "ICN"], ["ATL","SFO"]] ["ICN", "ATL", "ICN", "SFO", "ATL", "SFO"]

 

문제 풀이
  • 알파벳을 순서 조건을 해결하기위해 sort를 사용하여 tickets을 미리 정렬.
  • 정렬된 tickets에서 DFS를 수행하며, 제일 처음으로 탐색된 결과(n==false일때)를 answer에 저장한 후 더이상 탐색하지 않고 빠져나옴으로써 오버헤드를 크게 줄일 수 있음.
  • dfs 함수에 tickets 벡터를 전달하는 과정에서 포인터 전달을 통해 오버헤드를 줄임.
  • 포인터 참고: www.acmicpc.net/board/view/38804
 

글 읽기 - c++ string 과 vector 를 매개변수로 넘길때 질문입니다.

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

소스 코드
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
#include <string>
#include <vector>
#include <algorithm>
 
using namespace std;
 
vector<string> answer;
bool visited[10001];
bool n = 0;
 
bool compare(vector<string> a, vector<string> b)
{
    return a[1< b[1];
}
 
void DFS(vector<vector<string>> &tickets, string curr, vector<string> &path, int depth){
    if(depth == tickets.size()){
        answer = path;
        n = true;   
        return;
    }
 
    if(n == false){
        for(int i=0; i<tickets.size(); i++){
            if(!visited[i] && curr == tickets[i][0]){
                visited[i] = true;
                path.push_back(tickets[i][1]);
                DFS(tickets, tickets[i][1], path, depth+1);
                path.pop_back();
                visited[i] = false;
            }
        }
    }
}
 
vector<string> solution(vector<vector<string>> tickets) {
    vector<string> path;
 
    n = false;
    path.push_back("ICN");
    sort(tickets.begin(), tickets.end(), compare);
    DFS(tickets, "ICN", path, 0);
    
    return answer;
}

 

다른 사람의 풀이

  • DFS를 수행하는동안 얻어지는 path를 vector를 사용하지 않고, string에 결과를 더하는 방법을 사용.
  • 그래서 두개 이상의 경로에서 간단한 대소비교를 통해 알파벳이 앞서는 경로를 얻을 수 있음.
  • ans_string = "a"(0x61)로 초기 값을 준 이유는 제한사항 1번째인 모든 공항은 알파벳 대문자(0x40~0x5A)로 이루어져 있기때문. dfs 함수안에 path < ans_string 조건문의 첫번째 접근을 만족하려면 초기값은 0x5A보다 커야함.
  • dfs 함수에 tickets 벡터를 전달하는 과정에서 포인터 전달을 통해 오버헤드를 줄임.
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
#include <string>
#include <vector>
 
using namespace std;
int visited[1000000];
string ans_string = "a";
 
void dfs(vector<vector<string>> &tickets, string cur, string path, int depth) {
    if (depth == tickets.size()) {
        string p = path;
        if (path < ans_string) {
            ans_string = path;
        }
        return;
    }
 
    for (int i = 0; i < tickets.size(); i++) {
        if (cur == tickets[i][0&& !visited[i]) {
            visited[i] = 1;
            dfs(tickets, tickets[i][1], path + tickets[i][1], depth+1);
            visited[i] = 0;
        }
    }
}
 
vector<string> solution(vector<vector<string>> tickets) {
    vector<string> answer;
    dfs(tickets, "ICN""ICN"0);
    for (int i = 0; i < ans_string.size(); i+=3) {
        answer.push_back(ans_string.substr(i, 3));
    }
    return answer;
}