본문 바로가기

코딩테스트

[프로그래머스] level2. 게임 맵 최단거리 (javascript)

반응형

문제

ROR 게임은 두 팀으로 나누어서 진행하며, 상대 팀 진영을 먼저 파괴하면 이기는 게임입니다. 따라서, 각 팀은 상대 팀 진영에 최대한 빨리 도착하는 것이 유리합니다.

지금부터 당신은 한 팀의 팀원이 되어 게임을 진행하려고 합니다. 다음은 5 x 5 크기의 맵에, 당신의 캐릭터가 (행: 1, 열: 1) 위치에 있고, 상대 팀 진영은 (행: 5, 열: 5) 위치에 있는 경우의 예시입니다.

위 그림에서 검은색 부분은 벽으로 막혀있어 갈 수 없는 길이며, 흰색 부분은 갈 수 있는 길입니다. 캐릭터가 움직일 때는 동, 서, 남, 북 방향으로 한 칸씩 이동하며, 게임 맵을 벗어난 길은 갈 수 없습니다.
아래 예시는 캐릭터가 상대 팀 진영으로 가는 두 가지 방법을 나타내고 있습니다.

첫 번째 방법은 11개의 칸을 지나서 상대 팀 진영에 도착했습니다.

두 번째 방법은 15개의 칸을 지나서 상대팀 진영에 도착했습니다.

위 예시에서는 첫 번째 방법보다 더 빠르게 상대팀 진영에 도착하는 방법은 없으므로, 이 방법이 상대 팀 진영으로 가는 가장 빠른 방법입니다.

만약, 상대 팀이 자신의 팀 진영 주위에 벽을 세워두었다면 상대 팀 진영에 도착하지 못할 수도 있습니다. 예를 들어, 다음과 같은 경우에 당신의 캐릭터는 상대 팀 진영에 도착할 수 없습니다.

게임 맵의 상태 maps가 매개변수로 주어질 때, 캐릭터가 상대 팀 진영에 도착하기 위해서 지나가야 하는 칸의 개수의 최솟값을 return 하도록 solution 함수를 완성해주세요. 단, 상대 팀 진영에 도착할 수 없을 때는 -1을 return 해주세요.

나의풀이(오답)

function solution(maps) {
    var answer = 0;
    let location = [0,0];
    let goal = [4,4];
    let method = [];
    let cnt = 0;
    let visited = maps.map(el=>el.map(element=>0));

    function move(cnt,x,y){
        cnt++
        if(x==4 && y == 4 ){
            method.push(cnt)
            return
        }

        if(maps[x][y] !==0 && visited[x][y] !==1){
            location = [x,y]
        } else{
            return
        }

        move(cnt,location[0]+1,location[1])
        move(cnt,location[0],location[1]+1)
        move(cnt,location[0]-1,location[1])
        move(cnt,location[0],location[1]-1)
    }

    move(0,0,0)
    return answer;
}

재귀함수를 이용해서 상하좌우를 확인해서 x,y가 4일 경우를 찾으려고 시도했으나 실패.

다른이의 풀이

방법1. 배열을 통한 방향 설정 및 while문 & shift이용

 

function solution(maps) {
    let answer = -1;
    let xpos = [0,0,1,-1];
    let ypos = [1,-1,0,0];

    const q = [[0,0,1]];
    while(q.length != 0){
        let val = q.shift()
        let y=val[0];
        let x=val[1];
        let cnt=val[2];
        if (y === maps.length-1 && x === maps[0].length-1){
            answer = cnt
            break;
        }
        for(let i = 0; i < 4;i++){
            let yy = y + ypos[i];
            let xx = x + xpos[i];

            if (yy < 0 || xx < 0 || xx>=maps[0].length || yy>=maps.length){
            continue
            }
            if(maps[yy][xx] ==0 ){
                continue
            }
            if(maps[yy][xx] ==2 ){
                continue
            }
            maps[yy][xx] =2
            q.push([yy,xx,cnt+1])
        }
    }
    return answer;
}

 

여기서는 visited 배열을 따로 만들지 않고 , 방문한 배열에 2를 넣어주면서 표시하였다.

bfs 를 이제야 이해한듯하다.

dfs가 재귀 혹은 stack(pop)을 사용하는것이다!

 

방법2.

function solution(maps) {

    var yLen = maps.length - 1;
    var xLen = maps[0].length - 1;

    var queue = [[0, 0]];

    var visited = Array.from(new Array(maps.length), () => new Array(maps[0].length).fill(false));

    var result = 0;

    while (queue.length) {
        result++;
        var size = queue.length;
        for (var i = 0; i < size; i++) {
            var point = queue.shift();
            var curY = point[0];
            var curX = point[1];

            if (visited[curY][curX]) continue;

            maps[curY][curX] = 0;

            visited[curY][curX] = true;

            if (curY === yLen && curX === xLen) return result;

            if (curY < yLen && maps[curY + 1][curX] === 1) queue.push([curY + 1, curX])
            if (curX < xLen && maps[curY][curX + 1] === 1) queue.push([curY, curX + 1])
            if (curY > 0 && maps[curY - 1][curX] === 1) queue.push([curY - 1, curX])
            if (curX > 0 && maps[curY][curX - 1] === 1) queue.push([curY, curX - 1])
        }
    }

    return -1;
}

 

visited(방문한 배열 표시)를 따로 만들었다. 또한 조금 더 직관적으로 경우를 나누어주었다.

 

나중에 다시 풀어보자

반응형