일부러 태그에 관련 알고리즘을 명시하지 않았습니다. 문제부터 시간을 들여 풀어보고 오시죠! 차도 한 잔 마시면서~ 산책도 좀 하면서 말이죠 ㅎㅎ. 그럼 화이팅입니다!
문제: https://softeer.ai/practice/info.do?idx=1&eid=580
문제는 잘 풀어보셨나요? 저는 이 문제를 풀면서 아래와 같은 생각을 했어요.
문제를 읽으면서 2차원 배열을 만들어야겠다는 생각이 들었습니다.
그렇다면 2차원 배열을 단순히 순회하면서 탐색
하는 것인지, 아니면 백트랙킹
을 해야 하는 것인지 판단해야합니다. 이 문제는 단순탐색이었습니다. 단순탐색이기에 임시로 방문을 기록했다가 빼는 로직을 작성하지 않아도 되겠다는 생각이 들었어요.
순회를 허락하는 조건을 이해해야합니다.
교차로의 진입 방향
, 현재 시간
, 그리고 현재시간에 따른 교차로의 신호
가 순회에 영향을 줍니다.진입 방향
에 따라 신호를 받을 수도, 아닐 수도 있음을 인지하고 이를 코드로 구현해야 합니다. 저는 처음에 문제를 제대로 안 읽고 구현을 해서 매우 많이 틀렸습니다 ㅋㅋㅋㅋㅋ.교차로의 진입 방향
에 대한 정의
오른쪽
이었고, 그 차가 위
, 오른쪽
, 아래
세 가지의 방향을 갈 수 있다는 신호로 이해하는거죠. const intersectionInfo = require('fs')
.readFileSync(0)
.toString()
.trim()
.split('\n')
.map((line) => line.split(' ').map(Number))
const [N, T] = intersectionInfo.shift()
//신호번호에 따라 갈 수 있는 방향을 기록한 객체
const signalInfo = {
1: ['up', 'right', 'down'],
2: ['left', 'up', 'right'],
3: ['up', 'left', 'down'],
4: ['left', 'down', 'right'],
5: ['up', 'right'],
6: ['left', 'up'],
7: ['left', 'down'],
8: ['down', 'right'],
9: ['right', 'down'],
10: ['up', 'right'],
11: ['up', 'left'],
12: ['left', 'down'],
}
//진입 방향에 따라 진행할 수 있는 신호를 기록한 객체
const availableSignals = { up: [2, 6, 10], right: [1, 5, 9], down: [4, 8, 12], left: [3, 7, 11] }
//진행 방향에 따라 row, column의 변화(delta)를 기록한 객체
const dirToDelta = { up: [-1, 0], right: [0, 1], down: [1, 0], left: [0, -1] }
//유효한 2차원 배열 좌표값인지 검증하는 함수
function validateCoorditate(x, y) {
return x >= 0 && y >= 0 && x < N && y < N
}
//중복으로 세는 것을 방지하기 위해 방문을 기록하는 2차원 배열
const visitedMap = Array.from(Array(N), () => new Array(N).fill(0))
let answer = 0
//본격적인 재귀함수 - dfs방식의 탐색을 실행하기 위함
function recursion({ currentRow, currentColumn }, currDir, currentT) {
//재귀 종료 조건 - 유효한 시간이 아닐 때
if (currentT > T) {
return
}
//현재 좌표는 유효하니 방문처리를 해줌
if (visitedMap[currentRow][currentColumn] === 0) {
visitedMap[currentRow][currentColumn] = 1
answer++
}
//현재 몇 번째 교차로에 있는지
const currentIntersectionIndex = currentRow * N + currentColumn
//이 교차로는 현재 어떤 신호를 주고 있는지
const currentSignal = intersectionInfo[currentIntersectionIndex][currentT % 4]
//현재 교차로의 신호가 진입 방향에 유효한지 ~ 유효하면 진행시켜!
if (availableSignals[currDir].includes(currentSignal)) {
const candidateDirections = signalInfo[currentSignal]
//신호에 따라서 진행방향이 여러개니, for문을 통해 각각 순회
for (const nextDir of candidateDirections) {
const [rowDelta, columnDelta] = dirToDelta[nextDir]
const nextRow = currentRow + rowDelta
const nextColumn = currentColumn + columnDelta
//다음에 방문할 좌표가 유효한 좌표일때만 재귀 진행
if (!validateCoorditate(nextRow, nextColumn)) continue
//쪼로록~ 선택한 방향으로 다음 탐색을 이어 진행합니다
recursion({ currentRow: nextRow, currentColumn: nextColumn }, nextDir, currentT + 1)
}
}
}
recursion({ currentRow: 0, currentColumn: 0 }, 'up', 0)
console.log(answer)
일단 노가다로 구현
하고 최적화는 나중에
였습니다.
복잡한 문제네요 잘 보고 갑니다🍀