문제
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(방문한 배열 표시)를 따로 만들었다. 또한 조금 더 직관적으로 경우를 나누어주었다.
나중에 다시 풀어보자
'코딩테스트' 카테고리의 다른 글
[프로그래머스] level2. 영어 끝말잇기 (javascript) (0) | 2021.05.31 |
---|---|
[프로그래머스] level2. 스킬트리 (javascript) (0) | 2021.05.31 |
[프로그래머스] level2. 방문길이 (javascript) (0) | 2021.05.27 |
[프로그래머스]level2. 최댓값 최솟값 (javascript) (0) | 2021.05.16 |
[프로그래머스] level2. 위장 (javascript) (0) | 2021.05.16 |