개발자 톡
연습문제 톡
함께하는 효도
[JS풀이 공유]함께하는 효도 마지막 테스트 케이스만 틀리시는 분들 있으신가요?
- 등록일
- 2025-04-12 16:24:33
- 조회수
- 21
- 작성자
- asksue12
제출 코드 :
const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); let lineNo = 0; const dir = [[-1,0], [0,1], [1,0], [0, -1]]; let n, m; const arr = []; const fArr = []; const isOk = (i, j) => { return i >=1 && i<=n && j>=1 && j<=n; } const solve = () => { const searchRoute = (curFIndex) => { const result = []; const findARoute = () => { const visited = Array.from({length: n+1}, () => new Array(n+1).fill(false)); const s = []; const curFI = fArr[curFIndex][0]; const curFJ = fArr[curFIndex][1] s.push({i:curFI, j: curFJ, time: 0, num: arr[curFI][curFJ]}) visited[curFI][curFJ] = true; const dfs = (curI, curJ, curTime) => { if (curTime ===3) { result.push([{i:curFI, j: curFJ, time: 0, num: arr[curFI][curFJ]}, ...s.slice(0,)]); return; } for (let i=0; i<4; i+=1) { const [newI, newJ] = [curI + dir[i][0], curJ + dir[i][1]]; if (isOk(newI, newJ) && !visited[newI][newJ]) { visited[newI][newJ] = true; s.push({i:newI, j:newJ, time: curTime+1, num: arr[newI][newJ]}); dfs(newI, newJ, curTime + 1); visited[newI][newJ] = false; s.pop(); } } }; while(s.length>0) { const {i, j, time} = s.pop(); dfs(i, j, time); } } findARoute(); return result; } // 1. 가능한 루트 dfs로 다 탐색 const allRoute = []; for (let i=0; i<fArr.length; i+=1) { allRoute.push(searchRoute(i)); } // 2. 그 경로들로 dfs로 전부 탐색 let foundedR = []; const visitedTime = Array.from({length: 4}, () => Array.from({length:n+1}, () => new Array(n+1).fill(false))); const visitedFruit = Array.from({length:n+1}, () => new Array(n+1).fill(0)); const s = []; const dfs = (fIndex) => { if (fIndex === m) { foundedR.push(s.slice(0,)); return; } const routes = allRoute[fIndex]; // 여기서 for돌면서 하나 고르고. for (const r of routes) { // 그 루트 돌면서 체크. // 그 시간에 없는지 // if (r.every((x) => !visitedTime[x.time][x.i][x.j] && !visitedFruit[x.i][x.j])) { if (r.every((x) => !visitedTime[x.time][x.i][x.j])) { // + 남이 따간 곳 방문하면 num 0으로 바꾸는 로직 추가 const processedR = r.map((x) => { if (visitedFruit[x.i][x.j]>0) return {...x, num: 0}; else return x; }) // 없으면 방문 체크 후 push r.forEach((x) => { visitedTime[x.time][x.i][x.j] = true; visitedFruit[x.i][x.j] += 1; }); // s.push(r); s.push(processedR); // dfs dfs(fIndex+1); // 방문 해제 후 pop r.forEach((x) => { visitedTime[x.time][x.i][x.j] = false; visitedFruit[x.i][x.j] -= 1; }); s.pop(); } } } dfs(0); let max = 0; for (const fR of foundedR) { max = Math.max(max, fR.reduce((a, b) => a + b.reduce((aa, bb) => aa + bb.num, 0), 0)); } console.log(max); }; rl.on('line', (line) => { if (lineNo === 0) { [n,m] = line.split(" ").map((x) => 1 * x); arr.push(new Array(n+1).fill(-1)); } else if (lineNo <=n) arr.push([-1, ...line.split(" ").map((x) => 1 * x)]); else fArr.push(line.split(" ").map((x) => 1 * x)); lineNo+=1; }).on('close', () => { solve(); process.exit(0); });
풀이:
알고리즘 문제풀이가 너무 오랜만이라 아직 코드가 많이 조잡합니다. 죄송합니다..
- 각 친구들이 이동 가능한 모든 경로를 dfs로 구합니다.
- 그 경로 중에서, 같은 시간에, 같은 장소에만 없으면 허용이라는 조건을 만족하는 경로들을 dfs로 전부 찾습니다.
- 그렇게 찾은 경로에서 max 값을 찾아 출력합니다.
처음에 저는 루트를 결정할 때 그 시간에, 그 좌표에 겹치지 않기 + 다른 친구가 방문한 좌표면 가지 않기 라고 생각해서
if (r.every((x) => !visitedTime[x.time][x.i][x.j] && !visitedFruit[x.i][x.j]))
이렇게 풀었더니, 마지막 테스트케이스만 틀렸습니다.
뭐가 문제일까, 생각을 해보니 문제에서 "한 나무에 여러 친구가 방문하게 되더라도 열매는 딱 한 번만 수확이 가능합니다"라고 하는 것을 발견했습니다.
즉 visited 처리 이슈였습니다.
그래서 true/false로 관리하던 방문한 좌표를 숫자로 바꿔서 (친구들 중 1명 이상 방문할 수 있으니)
const visitedFruit = Array.from({ length: n + 1 }, () => new Array(n + 1).fill(0) );
방문할 때마다 카운트를 올리고, dfs에서 return 할 때 하나씩 내리고
해당 좌표의 카운트가 0일 때에만 열매 개수를 그대로 올리고, 0이 아니면 남은 열매 개수를 0으로 하여 경로를 저장해두고
그 경로 중 max값을 출력하니 마지막 테스트케이스도 통과했습니다!
혹시 저와 같은 이유로 막혀있으신 분들 계실 수도 있을 것 같아 공유합니다.
#함께하는_효도
#dfs
#예외처리