• [Lv2] 배달

    2021. 6. 26.

    by. 창고

    https://programmers.co.kr/learn/courses/30/lessons/12978?language=javascript 

     

    코딩테스트 연습 - 배달

    5 [[1,2,1],[2,3,3],[5,2,2],[1,4,2],[5,3,1],[5,4,2]] 3 4 6 [[1,2,1],[1,3,2],[2,3,2],[3,4,3],[3,5,2],[3,5,3],[5,6,1]] 4 4

    programmers.co.kr


    양방향이고, 한 도시에 도달할 수 있는 경로가 여러개인 경우,

     

    '방문했던 도시는 다시 방문하지 않는다'의 조건문을 만드는게 아니라,

     

    '특정 도시에 두 번 방문할 때, 이전에 방문한 경우보다 비용이 더 많이 드는 경우 방문하지 않는다'의 조건문이 필요함.

     

    아래 그림 참고

     

     

     

     

    1. TEST CASE 32번 통과하지 못한 코드

    // ***condition***
    // 1<=N<=50
    // 1<=road.len<=2,000
    // road = [start, end, time]
    // 1<=K<=500,000
    
    
    function solution(N, road, K) {
        var map = new Map();
        var visited = new Set().add(1);
    
        for(let [start, end, time] of road) {
            if(!map.has(start)) {
                map.set(start,[[end, time]]);
            } else if(map.has(start)) {
                let info = map.get(start);
                info.push([end, time]);
                map.set(start, info);
            }
            if(!map.has(end)) {
                map.set(end,[[start, time]]);
            } else if(map.has(end)) {
                let info = map.get(end);
                info.push([start, time]);
                map.set(end, info);
            }
        }
        
        let connectedCity = map.get(1);
        for(let [nextCity, time] of connectedCity) {
            if(time <= K) {
                visited.add(nextCity);
                search(nextCity, time, [1, nextCity]);
            }
        }
        
        function search(city, accTime, visiting) {
            if([...visited].length === N) return;
            
            let connectedCity = map.get(city);
            if(connectedCity) {
                for(let [nextCity, time] of connectedCity) {
                    if(visiting.includes(nextCity) || accTime + time > K) continue;
                    else {
                        visited.add(nextCity);
                        search(nextCity, accTime + time, [...visiting, nextCity]);
                    }
                }
            }
        }
        
        return [...visited].length;
    }

     

    2. TEST CASE 32번 통과한 코드

    function solution(N, road, K) {
        var map = new Map();
        var visited = new Set().add(1);
        var visitedTime = new Map().set(1, 0);
    
    
        // 연결 정보를 모두 객체에 저장
        // 한 도로의 정보가 여러 번 중복해서 주어지지 않으므로, End도 저장해주어야 함.
        for(let [start, end, time] of road) { 
            if(!map.has(start)) {
                map.set(start,[[end, time]]);
            } else if(map.has(start)) {
                let info = map.get(start);
                info.push([end, time]);
                map.set(start, info);
            }
            if(!map.has(end)) {
                map.set(end,[[start, time]]);
            } else if(map.has(end)) {
                let info = map.get(end);
                info.push([start, time]);
                map.set(end, info);
            }
        }
        
        // 출발 지점 도시1을 기준으로 주변 도시 탐색
        let connectedCity = map.get(1);
        for(let [nextCity, time] of connectedCity) {
            if(time <= K) {
                visited.add(nextCity);
                visitedTime.set(nextCity, time);
                search(nextCity, time, [1, nextCity]);
            }
        }
        
        function search(city, accTime, visiting) {
            if([...visited].length === N) return; // 모든 도시의 탐색이 끝난 경우
            if(visitedTime.get(city) < accTime) return; // 해당 도시를 더 짧은 시간에 방문한 경우
            
            let connectedCity = map.get(city);
    
            if(connectedCity) { // 본 문제에선 문제가 안되지만, 다른곳에서는 문제가 될 수 있음. 항상 체크하자!
                for(let [nextCity, time] of connectedCity) {
                    if(visiting.includes(nextCity) || accTime + time > K) continue;
                    else {
                        visited.add(nextCity);
                        if(!visitedTime.has(nextCity) || visitedTime.get(nextCity) > accTime + time) 
                            visitedTime.set(nextCity, accTime + time);
                        search(nextCity, accTime + time, [...visiting, nextCity]);
                    }
                }
            }
        }
        
        return [...visited].length;
    }

    3. 다른 사람 풀이 Dijkstra algorithm 

    https://juyoungpark718.github.io/posts/60

     

    [프로그래머스] 레벨3 (level3) 배달

    배달 문제설명 N개의 마을로 이루어진 나라가 있습니다. 이 나라의 각 마을에는 1부터 N까지의 번호가 각각 하나씩 부여되어 있습니다. 각 마을은 양방향으로 통행할 수 있는 도로로 연결되어 있

    juyoungpark718.github.io

    위 사이트를 참고하여 코드 변수명을 아래와 같이 수정함.

    function solution(N, road, K) {
        var answer = 0;
        var minTime = new Array(N+1).fill(Infinity);
        var adj = new Array(N+1).fill(0).map(val => {return new Array()});
    
        for(let info of road) {
            let [start, end, time] = info;
    
            adj[start].push({ to : end , weight : time });
            adj[end].push({ to : start, weight : time });
        }
    
        let q = [{to : 1, weight : 0}];
        minTime[1] = 0;
        
        
        while(q.length) {
            let visited = q.pop();
            
            adj[visited.to].forEach(info => {
                if(minTime[info.to] > minTime[visited.to] + info.weight) {
                    minTime[info.to] = minTime[visited.to] + info.weight;
                    q.push(info);
                }
            });
        }
    
        minTime.forEach(val => {
            if(val <= K) answer++;
        })
        
        return answer;
    }

    '알고리즘 > 프로그래머스' 카테고리의 다른 글

    [Lv2] 순위 검색  (0) 2021.07.04
    [Lv2] 수식 최대화  (0) 2021.07.01
    [Lv2] 124 나라 숫자  (0) 2021.06.21
    [Lv3] 입국심사  (0) 2021.06.16
    [Lv2] 멀쩡한 사각형  (0) 2021.06.14

    댓글