728x90
예외처리가 조금 복잡한 BFS문제였다.
아래 항목들만 생각하면 문제에 조금 쉽게 접근할 수 있다.
1. 한턴에 빨간공,파란공은 한번씩 움직인다.
2. 빨간공이나 파란공이 도착했다면 더이상 움직이지 않는다.
3. 두 공은 같은 위치로 움직일 수 없다.
4. 두 공은 서로 교차하며 움직일 수 없다.
1번에서 특히 빨간공 파란공이 한번에 움직인다는 점에 포커스를 두면 된다.
BFS를 통해서 빨간공을 상,하,좌,우로 움직이는 경우마다 파란공또한 움직이면 된다.
map의 size가 5*5로 주어지는 이유이다. 총 16가지의 경우의 수들을 한 턴마다 증가시키면서 검사해야하기 때문이다.
function solution(maze) {
const rLen = maze.length
const cLen = maze[0].length
const dc = [1,0,-1,0]
const dr = [0,1,0,-1]
//방문배열 생성
const redVisited = maze.map(v => Array(cLen).fill(false))
const blueVisited = maze.map(v => Array(cLen).fill(false))
//맵 정보 저장
let redCood,blueCood,redDest,blueDest
for (let i = 0 ; i < rLen ; i++){
for (let j = 0 ; j < cLen ; j++){
if(maze[i][j]===1) {
redCood = [i,j]
redVisited[i][j] = true
}
if(maze[i][j]===2) {
blueCood= [i,j]
blueVisited[i][j] = true
}
if(maze[i][j]===3) redDest= [i,j]
if(maze[i][j]===4) blueDest= [i,j]
}
}
const isEqualAry = (a,b) => {
for (let i =0 ; i <a.length ; i++){
if(a[i]!==b[i]) return false
}
return true
}
const isCanMove = (r,c,visited,otherR,otherC) => {
if (0<=r&&r<rLen&&0<=c&&c<cLen&&!visited[r][c]&&maze[r][c]!==5&&(otherR!==r||otherC!==c)) return true
return false
}
let ret = Infinity
const dfs = (redCood,blueCood,cnt) => {
//둘다 도착한 경우
if(isEqualAry(redCood,redDest) && isEqualAry(blueCood,blueDest)) {
ret = Math.min(ret,cnt)
return
}
if(isEqualAry(redCood,redDest)){ //red만 도착한 경우
for (let bd = 0 ; bd < 4 ; bd++){
const [nBlueR,nBlueC] = [blueCood[0] + dr[bd] , blueCood[1] + dc[bd]]
if(isCanMove(nBlueR,nBlueC,blueVisited,...redCood)){
blueVisited[nBlueR][nBlueC] = true
dfs(redCood,[nBlueR,nBlueC],cnt+1)
blueVisited[nBlueR][nBlueC] = false
}
}
}else if(isEqualAry(blueCood,blueDest)){ //blue만 도착한 경우
for (let rd = 0 ; rd < 4 ; rd++){
const [nRedR,nRedC] = [redCood[0] + dr[rd] , redCood[1] + dc[rd]]
if(isCanMove(nRedR,nRedC,redVisited,...blueCood)){
redVisited[nRedR][nRedC] = true
dfs([nRedR,nRedC],blueCood,cnt+1)
redVisited[nRedR][nRedC] = false
}
}
} else { //둘다 도착하지 않음
for (let rd = 0 ; rd < 4 ; rd++){
const [nRedR,nRedC] = [redCood[0] + dr[rd] , redCood[1] + dc[rd]]
if(isCanMove(nRedR,nRedC,redVisited,[-1,-1])){
redVisited[nRedR][nRedC] = true
for (let bd = 0 ; bd < 4 ; bd++){
const [nBlueR,nBlueC] = [blueCood[0] + dr[bd] , blueCood[1] + dc[bd]]
if(isCanMove(nBlueR,nBlueC,blueVisited,nRedR,nRedC) &&
!(isEqualAry([nBlueR,nBlueC],redCood) && isEqualAry(blueCood,[nRedR,nRedC])
//서로 뒤바뀌며 움직이는 경우 체크
)){
blueVisited[nBlueR][nBlueC] = true
dfs([nRedR,nRedC],[nBlueR,nBlueC],cnt+1)
blueVisited[nBlueR][nBlueC] = false
}
}
redVisited[nRedR][nRedC] = false
}
}
}
}
dfs(redCood,blueCood,0)
return ret=== Infinity ? 0 : ret
}
728x90
'FrontEnd > 프로그래머스' 카테고리의 다른 글
[JS] 110옮기기 (1) | 2023.12.06 |
---|---|
[JS] 아날로그 시계 (1) | 2023.12.03 |
[JS] 석유 시추 (1) | 2023.12.01 |
[JS] 붕대 감기 (0) | 2023.11.27 |
[JS] 퍼즐조각 채우기 (1) | 2023.11.21 |