Logo
Hyunsu Blog
algorithm-backtracking

๐Ÿ“†Published :Jan 27, 2024 โ€ข

๐Ÿ“†Updated :Jan 27, 2024 โ€ข

โ˜•๏ธ1min

๋ฐฑํŠธ๋ž˜ํ‚น

  • ๋ฐฑํŠธ๋ž˜ํ‚น ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ•ต์‹ฌ์€ 'ํ•ด๊ฐ€ ๋  ๊ฐ€๋Šฅ์„ฑ์„ ํŒ๋‹จ'ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • ์—ฌ๊ธฐ์„œ์˜ ๊ฐ€๋Šฅ์„ฑ์€ ์œ ๋ง ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋ฉด์„œ ํŒ๋‹จํ•œ๋‹ค.

๋ฌธ์ œ๋ฅผ ํ’€๋ฉด์„œ ์ต์ˆ™ํ•ด์ง€๋Š”๊ฒŒ ์ค‘์š”ํ•œ๊ฒƒ ๊ฐ™๋‹ค.

๋ฌธ์ œ ํ’€์ด

ํ”ผ๋กœ๋„

๋ฌธ์ œ XX๊ฒŒ์ž„์—๋Š” ํ”ผ๋กœ๋„ ์‹œ์Šคํ…œ(0 ์ด์ƒ์˜ ์ •์ˆ˜๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค)์ด ์žˆ์œผ๋ฉฐ, ์ผ์ • ํ”ผ๋กœ๋„๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋˜์ „์„ ํƒํ—˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ, ๊ฐ ๋˜์ „๋งˆ๋‹ค ํƒํ—˜์„ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ "์ตœ์†Œ ํ•„์š” ํ”ผ๋กœ๋„"์™€ ๋˜์ „ ํƒํ—˜์„ ๋งˆ์ณค์„ ๋•Œ ์†Œ๋ชจ๋˜๋Š” "์†Œ๋ชจ ํ”ผ๋กœ๋„"๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. "์ตœ์†Œ ํ•„์š” ํ”ผ๋กœ๋„"๋Š” ํ•ด๋‹น ๋˜์ „์„ ํƒํ—˜ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•˜๋Š” ์ตœ์†Œํ•œ์˜ ํ”ผ๋กœ๋„๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, "์†Œ๋ชจ ํ”ผ๋กœ๋„"๋Š” ๋˜์ „์„ ํƒํ—˜ํ•œ ํ›„ ์†Œ๋ชจ๋˜๋Š” ํ”ผ๋กœ๋„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด "์ตœ์†Œ ํ•„์š” ํ”ผ๋กœ๋„"๊ฐ€ 80, "์†Œ๋ชจ ํ”ผ๋กœ๋„"๊ฐ€ 20์ธ ๋˜์ „์„ ํƒํ—˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์œ ์ €์˜ ํ˜„์žฌ ๋‚จ์€ ํ”ผ๋กœ๋„๋Š” 80 ์ด์ƒ ์ด์–ด์•ผ ํ•˜๋ฉฐ, ๋˜์ „์„ ํƒํ—˜ํ•œ ํ›„์—๋Š” ํ”ผ๋กœ๋„ 20์ด ์†Œ๋ชจ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒŒ์ž„์—๋Š” ํ•˜๋ฃจ์— ํ•œ ๋ฒˆ์”ฉ ํƒํ—˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋˜์ „์ด ์—ฌ๋Ÿฌ๊ฐœ ์žˆ๋Š”๋ฐ, ํ•œ ์œ ์ €๊ฐ€ ์˜ค๋Š˜ ์ด ๋˜์ „๋“ค์„ ์ตœ๋Œ€ํ•œ ๋งŽ์ด ํƒํ—˜ํ•˜๋ ค ํ•ฉ๋‹ˆ๋‹ค. ์œ ์ €์˜ ํ˜„์žฌ ํ”ผ๋กœ๋„ k์™€ ๊ฐ ๋˜์ „๋ณ„ "์ตœ์†Œ ํ•„์š” ํ”ผ๋กœ๋„", "์†Œ๋ชจ ํ”ผ๋กœ๋„"๊ฐ€ ๋‹ด๊ธด 2์ฐจ์› ๋ฐฐ์—ด dungeons ๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ฃผ์–ด์งˆ ๋•Œ, ์œ ์ €๊ฐ€ ํƒํ—˜ํ• ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๋˜์ „ ์ˆ˜๋ฅผ return ํ•˜๋„๋ก solution ํ•จ์ˆ˜๋ฅผ ์™„์„ฑํ•ด์ฃผ์„ธ์š”.

์ด ๋ฌธ์ œ๋Š” ๊ฐ ๋˜์ „์„ ํƒํ—˜ํ•˜๊ธฐ ์ง์ „ ํ˜„์žฌ ํ”ผ๋กœ๋„์™€ ์ตœ์†Œ ํ•„์š” ํ”ผ๋กœ๋„์™€๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ฐ€์ง€์น˜๊ธฐ๋ฅผ ํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ์œ ๋งํ•จ์ˆ˜๋Š” ์ด๋ฏธ ๋ฐฉ๋ฌธํ•œ ๋˜์ „์„ ํ™•์ธํ•˜๋Š” ์กฐ๊ฑด๊ณผ ํ˜„์žฌ ํ”ผ๋กœ๋„๊ฐ€ ์ตœ์†Œํ•„์š”ํ”ผ๋กœ๋„๋ณด๋‹ค ๋” ์ž‘๋‹ค๋Š” ์กฐ๊ฑด์„ ํฌํ•จํ•œ๋‹ค.

if (visited.has(i)) continue // ํ˜„์žฌํ”ผ๋กœ๋„์™€ ์ตœ์†Œ ํ•„์š” ํ”ผ๋กœ๋„ ๋น„๊ต const [required, consumed] = dungeons[i] if (cur < required) continue function solution(k, dungeons) { let max = 0 let visited = new Set() let numOfDungeons = dfs(0, k, 0, visited, 0) return numOfDungeons function dfs(level, cur, cnt, visited, max) { for (let i = 0; i < dungeons.length; i++) { if (visited.has(i)) continue // ํ˜„์žฌํ”ผ๋กœ๋„์™€ ์ตœ์†Œ ํ•„์š” ํ”ผ๋กœ๋„ ๋น„๊ต const [required, consumed] = dungeons[i] if (cur < required) continue visited.add(i) cnt += 1 max = Math.max(max, visited.size) max = dfs(level + 1, cur - consumed, cnt, visited, max) visited.delete(i) } return max } }

N-Queen ์ถœ์ฒ˜: ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค

๋ฌธ์ œ ๊ฐ„๋žต ์„ค๋ช… ๊ฐ€๋กœ, ์„ธ๋กœ ๊ธธ์ด๊ฐ€ n์ธ ์ •์‚ฌ๊ฐํ˜•์œผ๋กœ๋œ ์ฒด์ŠคํŒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒด์ŠคํŒ ์œ„์˜ n๊ฐœ์˜ ํ€ธ์ด ์„œ๋กœ๋ฅผ ๊ณต๊ฒฉํ•  ์ˆ˜ ์—†๋„๋ก ๋ฐฐ์น˜ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.์ฒด์ŠคํŒ์˜ ๊ฐ€๋กœ ์„ธ๋กœ์˜ ์„ธ๋กœ์˜ ๊ธธ์ด n์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ฃผ์–ด์งˆ ๋•Œ, n๊ฐœ์˜ ํ€ธ์ด ์กฐ๊ฑด์— ๋งŒ์กฑ ํ•˜๋„๋ก ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์˜ ์ˆ˜๋ฅผ returnํ•˜๋Š” solutionํ•จ์ˆ˜๋ฅผ ์™„์„ฑํ•ด์ฃผ์„ธ์š”. ์ œํ•œ์‚ฌํ•ญ ํ€ธ(Queen)์€ ๊ฐ€๋กœ, ์„ธ๋กœ, ๋Œ€๊ฐ์„ ์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ n์ด 4์ธ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ€ธ์„ ๋ฐฐ์น˜ํ•˜๋ฉด n๊ฐœ์˜ ํ€ธ์€ ์„œ๋กœ๋ฅผ ํ•œ๋ฒˆ์— ๊ณต๊ฒฉ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ€ธ์˜ ๊ณต๊ฒฉ ๋ฒ”์œ„์— ๋“ค์–ด๊ฐ€๋Š” ๊ฒฝ์šฐ์ธ ๊ฐ™์€ ํ–‰, ๊ฐ™์€ ์—ด, ๊ฐ™์€ ๋Œ€๊ฐ์„ ์ด๋ผ๋Š” ์ ๊ณผ ๋ฌธ์ œ์—์„œ ๊ฐ€๋กœ์„ธ๋กœ ๊ธธ์ด n ๊ณผ n๊ฐœ์˜ ํ€ธ์„ ๋†“๋Š”๋‹ค ๋ผ๋Š” ์ ์„ ๊ทธ๋ƒฅ ๋„˜๊ธฐ๋ฉด ์•ˆ๋œ๋‹ค. ์ด ์ „ ํ€ธ์ด ์œ„์น˜ํ•œ ํ–‰๊ณผ ์—ด์—๋Š” ํ€ธ์„ ๋†“์„ ์ˆ˜ ์—†๋‹ค๋Š”๊ฒŒ ํ™•์‹คํ•˜๋‹ˆ ๊ฒฐ๊ตญ 1 ํ–‰์— 1๊ฐœ์˜ ํ€ธ ๋งŒ ๋†“์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿผ 2d ์ขŒํ‘œ๋ฅผ ์ˆœํšŒํ•˜๊ธฐ ์œ„ํ•ด ์ด์ค‘for๋ฌธ์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง„๋‹ค. ์ฃผ์–ด์ง„ ํ–‰์—์„œ ์–ด๋Š ์—ด์— ํ€ธ์„ ๋†“์œผ๋ฉด ๋˜๋Š”๊ฐ€๋ฅผ ๊ณ ๋ฏผํ•˜๋ฉด ๋œ๋‹ค.

function solution(n) { let cnt = 0 const isVisited_col = new Array(n).fill(-1) // isVisited_col[i] = j : i๋ฒˆ์งธ ๋ง (ํ–‰) ์€ j๋ฒˆ์งธ ์—ด์— ๋†“์—ฌ์žˆ๋‹ค. function isValidToPutQueen(currentX, currentY, prevX, prevY) { //chessboard ์— 8๋ฐฉํ–ฅ์œผ๋กœ ํ€ธ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. //ํ€ธ์ด ์žˆ๋‹ค๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. // 1. ๊ฐ™์€ ์—ด์— ํ€ธ์ด ์žˆ๋Š”์ง€ ํ™•์ธ. if (currentY === prevY) return false // 2. ๋Œ€๊ฐ์„  ์˜ค๋ฅธ์ชฝ์— ํ€ธ์ด ์žˆ๋Š”์ง€ ํ™•์ธ if (currentX + currentY === prevX + prevY) return false // 3. ๋Œ€๊ฐ์„  ์™ผ์ชฝ์— ํ€ธ์ด ์žˆ๋Š”์ง€ ํ™•์ธ if (currentX - currentY === prevX - prevY) return false return true } function recursiveNQueen(level) { if (level === n) { cnt += 1 //ํ•œ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์˜ ์ˆ˜๋ฅผ ์ฐพ์Œ return } //๋ฐฑํŠธ๋ž˜ํ‚น์„ ์ ์šฉํ•œ ๋ฒ„์ „ // nThQueen ์„ ๋†“์„ ์ˆ˜ ์žˆ๋Š” ์œ„์น˜(์—ด = col)๋ฅผ ์ฐพ๋Š”๋‹ค. // ์ฐพ๋Š” ๋‹ค๋Š”๊ฒƒ์€ ํƒ์ƒ‰ํ•œ๋‹ค๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์˜๋ฏธ์ด๋ฉฐ , ์—ฌ๊ธฐ์„œ ๋ฐฑํŠธ๋ž˜ํ‚น์€ ํƒ์ƒ‰์„ ํ•  ๋•Œ, // ํƒ์ƒ‰ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ฏธ๋ฆฌ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค. for (let i = 0; i < n; i++) { let isFinalValid = true // ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ์—ด์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ์ž‘์—…์„ ๋“ค์–ด๊ฐ€๊ธฐ ์ „์— isFinalValid๋ฅผ true๋กœ ์ดˆ๊ธฐํ™” ํ•ด์ค๋‹ˆ๋‹ค. for (let row = 0; row < level; row++) { // ์ฐฉ๊ฐ€ํ•˜์ง€ ๋ง๊ฒƒ : row๋ฅผ ๋ชจ๋‘ ํ™•์ธํ•ด์„œ ํ€ธ์ด ์—†์–ด์•ผ i์ž๋ฆฌ์— ํ€ธ์„ ๋†“์„์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. if (!isValidToPutQueen(level, i, row, isVisited_col[row])) { isFinalValid = false // isVisited_col[level] = i; // false๋ผ๋ฉด ๋”์ด์ƒ ํƒ์ƒ‰ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ชจ๋‘ validํ•ด์•ผ ์ตœ์ข…์ ์œผ๋กœ validํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”. break } } if (!isFinalValid) continue // ํ€ธ์„ ๋†“์„ ์ˆ˜ ์žˆ์Œ. isVisited_col[level] = i recursiveNQueen(level + 1, cnt) isVisited_col[level] = -1 } } recursiveNQueen(0) return cnt }

ํšŒ๊ณ 

์ด๋ฒˆ์ฃผ๋Š” ๋ฌธ์ œ๋ฅผ ๊ฑฐ์˜ ํ’€์ง€ ๋ชปํ–ˆ๋‹ค. ๋‚จ์€ ๊ธฐ๊ฐ„์— ๋ณด์ถฉ ํ•ด์„œ ํ’€์–ด๋ด์•ผ๊ฒ ๋‹ค.

Hi, I'm Hyunsu ๐Ÿ‘‹

Profile Image

์•ˆ๋…•ํ•˜์„ธ์š”. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ฃผํ˜„์ˆ˜์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ํ’๋ถ€ํ•˜๊ณ  ๊ฐ€์น˜ ์žˆ๋Š” ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š” ์ผ์— ๋ฟŒ๋“ฏํ•จ์„ ๋Š๋‚๋‹ˆ๋‹ค.

์˜ต์‹œ๋””์–ธ(Obsidian)์—์„œ ํ˜„์žฌ ๋ธ”๋กœ๊ทธ๋กœ ํ•˜๋‚˜์”ฉ ๊ธ€์„ ์˜ฎ๊ธฐ๋Š” ๊ณผ์ •์— ์žˆ์–ด์š”. โ˜•๏ธ ๐Ÿ‘ฉโ€๐Ÿ’ป โ›ท

Github on ViewReach Me Out