Skip to content

Latest commit

ย 

History

History
598 lines (429 loc) ยท 24.7 KB

basic.md

File metadata and controls

598 lines (429 loc) ยท 24.7 KB

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ธฐ๋ณธ

์ž‘์„ฑ์ž : ๊ถŒํ˜์ง„, ๋ฐ•์žฌ์šฉ, ์„œ๊ทธ๋ฆผ

Table of Contents

์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์™„์ „ํƒ์ƒ‰(Brute-Force, ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ํƒ์ƒ‰ํ•ด๋ณด๋Š” ๊ฒƒ)์—์„œ ์‹œ์ž‘ํ•œ๋‹ค. ์ด๋Š” ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๋‹ค ๋”ฐ์ ธ๋ณด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ์ตœ๋Œ€์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค. ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ์ƒ๊ฐํ•ด๋ณด๊ณ  ๋˜ํ•œ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ๊ทธ๋Ÿฌํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ƒ๊ฐํ•ด๋ณด๊ณ  ๊ทธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ •ํ™•ํ•˜๊ฒŒ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์งœ๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ ๊ณผ์ •์˜ ์—ฐ์Šต์ด ํ•„์š”ํ•˜๋‹ค.

  • ๋ฌธ์ œ๋ฅผ ํŒŒ์•…ํ•˜๊ณ  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ƒ๊ฐํ•˜๊ธฐ
  • ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๊ณต๊ฐ„๋ณต์žก๋„์™€ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๋ฌธ์ œ์˜ ์ œ์•ฝ ์กฐ๊ฑด ๋‚ด์— ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ธ์ง€ ํŒ๋‹จํ•˜๊ธฐ
  • ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋น ๋ฅด๊ณ  ์ •ํ™•ํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ (์—ฐ์Šต๋งŒ์ด ์ •๋‹ต)

์‹œ๊ฐ„๋ณต์žก๋„์™€ ๊ณต๊ฐ„๋ณต์žก๋„

๋ณต์žก๋„๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์„ฑ๋Šฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ฒ™๋„์ด๋‹ค.
๋ณต์žก๋„๋Š” ์‹œ๊ฐ„ ๋ณต์žก๋„(Time Complexity) ์™€ ๊ณต๊ฐ„ ๋ณต์žก๋„(Space Complexity) ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.
์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ํŠน์ •ํ•œ ํฌ๊ธฐ์˜ ์ž…๋ ฅ์— ๋Œ€ํ•˜์—ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์–ผ๋งˆ๋‚˜ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š”์ง€๋ฅผ ์˜๋ฏธํ•˜๊ณ  ๊ณต๊ฐ„ ๋ณต์žก๋„๋Š” ํŠน์ •ํ•œ ํฌ๊ธฐ์˜ ์ž…๋ ฅ์— ๋Œ€ํ•˜์—ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐจ์ง€ํ•˜๋Š”์ง€๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์žˆ๋‹ค๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ ๋ณต์žก๋„๊ฐ€ ๋‚ฎ์„์ˆ˜๋ก ์ข‹์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.
๋ณต์žก๋„์˜ ์ธก์ •์œผ๋กœ ์šฐ๋ฆฌ๋Š” '์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์œ„ํ•ด ํ•„์š”ํ•œ ์—ฐ์‚ฐ์˜ ํšŸ์ˆ˜'๋กœ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๊ณ  '์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ์˜ ์–‘'์œผ๋กœ ๊ณต๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์‹œ๊ฐ„ ๋ณต์žก๋„

๋ณดํ†ต ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ํ‘œํ˜„ํ•  ๋•Œ๋Š” Big-O ํ‘œ๊ธฐ๋ฒ•(Big-O notation)์„ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ฆ๊ฐ€ํ•˜๋Š” ํ•ญ๋งŒ ๊ณ ๋ คํ•˜๋Š” ํ‘œ๊ธฐ๋ฒ•์œผ๋กœ limit์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด N๊ฐœ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ์˜ ๊ฐ’์„ ๋”ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋ผ๋ฉด N๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์ฐจ๋ก€๋กœ NํšŒ ๋”ํ•ด์ค€๋‹ค. ์ด ๋•Œ ์—ฐ์‚ฐ ํšŸ์ˆ˜๋Š” N์— ๋น„๋ก€ํ•˜๊ณ  ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ์ถœ๋ ฅํ•˜๋Š” ์—ฐ์‚ฐ์€ ์ƒ๋Œ€์ ์œผ๋กœ N์ด ์ปค์ง„๋‹ค๋ฉด ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ๊ฐ€์žฅ ์˜ํ–ฅ๋ ฅ์ด ํฐ ๋ถ€๋ถ„์ด N์œผ๋กœ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ O(N)์œผ๋กœ ํ‘œ์‹œํ•œ๋‹ค.
์ผ๋ฐ˜์ ์œผ๋กœ ์ฝ”๋”ฉํ…Œ์ŠคํŠธ์—์„œ๋Š” ์ตœ์•…์˜ ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ์—ฐ์‚ฐ ํšŸ์ˆ˜๊ฐ€ ๊ฐ€์žฅ ์ค‘์š”ํ•˜๋ฏ€๋กœ ์ž์‹ ์ด ์ž‘์„ฑํ•œ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ  ๋ถ„์„ํ•˜์—ฌ ์ตœ์•…์˜ ๊ฒฝ์šฐ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค.
O(N3)์„ ๋„˜์–ด๊ฐ€๋ฉด ๋ฌธ์ œ ํ’€์ด์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ค์šด ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ N์ด 1000๊ฐœ๋ฅผ ๋„˜์–ด๊ฐ€๋ฉด 5์ดˆ ์ด์ƒ์˜ ์‹œ๊ฐ„์ด ์†Œ์š”๋  ๊ฒƒ์ด๋ผ๊ณ  ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

  • N์˜ ๋ฒ”์œ„๊ฐ€ 500์ธ ๊ฒฝ์šฐ) ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O(N3)์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค๊ณ„ํ•˜๋ฉด ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ
  • N์˜ ๋ฒ”์œ„๊ฐ€ 2000์ธ ๊ฒฝ์šฐ) ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O(N2)์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค๊ณ„ํ•˜๋ฉด ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ
  • N์˜ ๋ฒ”์œ„๊ฐ€ 100,000์ธ ๊ฒฝ์šฐ) ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O(Nlog N)์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค๊ณ„ํ•˜๋ฉด ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ
  • N์˜ ๋ฒ”์œ„๊ฐ€ 10,000,000์ธ ๊ฒฝ์šฐ) ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O(N)์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค๊ณ„ํ•˜๋ฉด ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ

๋ณดํ†ต 1์–ต(108)๋ฒˆ์˜ ์—ฐ์‚ฐ๋‹น 1์ดˆ์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค๊ณ  ๊ฐ„์ฃผํ•œ๋‹ค.

๊ณต๊ฐ„ ๋ณต์žก๋„

๊ณต๊ฐ„ ๋ณต์žก๋„๋ฅผ ํ‘œ๊ธฐํ•  ๋•Œ์—๋„ Big-O ํ‘œ๊ธฐ๋ฒ•(Big-O notation)์„ ์‚ฌ์šฉํ•œ๋‹ค.
์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ์—์„œ๋Š” ๋ณดํ†ต ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ 128~512MB๋กœ ์ œํ•œํ•˜๊ณ  ์žˆ๋‹ค. ์ฆ‰ ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜๊ฐ€ 1,000๋งŒ ๋‹จ์œ„๋ฅผ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋„๋ก ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ค๊ณ„๋ฅผ ํ•ด์•ผํ•˜๊ณ  100๋งŒ ๊ฐœ ์ด์ƒ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋Š” ํฌ๊ธฐ์˜ ๋ฐฐ์—ด์„ ์„ ์–ธํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๊ฑฐ์˜ ๋“œ๋ฌผ๋‹ค.
๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ๊ฐ€ 1,000๋งŒ ๋‹จ์œ„ ์ด์ƒ์ด๋ผ๋ฉด ์ž์‹ ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ž˜๋ชป ์„ค๊ณ„ํ•œ ๊ฒƒ์ด ์•„๋‹Œ์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ’€์ด์—์„œ์˜ ๋ณต์žก๋„๋Š” ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ์˜๋ฏธํ•œ๋‹ค.


DFS์™€ BFS

์Šคํ„ฐ๋”” ์ž๋ฃŒ - ์ž‘์„ฑ์ž ๊ถŒํ˜์ง„ | ๊นŠ์ด์šฐ์„ ํƒ์ƒ‰ DFS ์— ๋Œ€ํ•˜์—ฌ

DFS(Depth First Search, ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰)

  • ํ•œ ๊ฒฝ๋กœ๋กœ ์ตœ๋Œ€ํ•œ ๊นŠ์ˆ™ํ•˜๊ฒŒ ๋“ค์–ด๊ฐ€์„œ ํƒ์ƒ‰ํ•œ ํ›„ ๋‹ค์‹œ ๋Œ์•„๊ฐ€ ๋‹ค๋ฅธ ๊ฒฝ๋กœ๋กœ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ์‹
  • ์žฌ๊ท€ํ•จ์ˆ˜, Stack์„ ์ด์šฉํ•ด ๊ตฌํ˜„
  • ์œ ์˜ํ•  ์  : Stack Overflow (๊ธฐ์ €์กฐ๊ฑด ์ž˜ ์„ค์ •)
  • ํ™œ์šฉ : ๋ฐฑํŠธ๋ž˜ํ‚น, ๋‹จ์ ˆ์„ /๋‹จ์ ˆ์  ์ฐพ๊ธฐ, ์œ„์ƒ์ •๋ ฌ, ์‚ฌ์ดํด ์ฐพ๊ธฐ ๋“ฑ

DFS ๊ตฌํ˜„

void dfs(int current) {
    if (current == target) { // ๋ชฉ์ ์ง€์ธ๊ฐ€?
        System.out.println("๋ชฉ์ ์ง€์ž…๋‹ˆ๋‹ค.");
        return;
    }
    visited[current] = true; // ์ฒดํฌ์ธ
    for (int next : graph[current]) { // ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ณณ์„ ์ˆœํšŒ
        if (!visited[next]) { // ๊ฐˆ ์ˆ˜ ์žˆ๋Š”๊ฐ€?
            dfs(next); // ๊ฐ„๋‹ค
        }
    }
    visited[current] = false; // ์ฒดํฌ์•„์›ƒ
}

BFS(Breadth First Search, ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰)

  • ์‹œ์ž‘ ๋…ธ๋“œ์—์„œ ์‹œ์ž‘ํ•˜์—ฌ ์ธ์ ‘ํ•œ ๋…ธ๋“œ๋ฅผ ๋จผ์ € ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ์‹, ์—ฌ๋Ÿฌ ๊ฒฝ๋กœ ๋™์‹œ์— ํƒ์ƒ‰ ๊ฐ€๋Šฅ
  • Queue๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„
  • ์œ ์˜ํ•  ์  : ๋ฉ”๋ชจ๋ฆฌ ์ดˆ๊ณผ (๋ฐฉ๋ฌธ ์ฒดํฌ ๊ผญ ํ•ด์ค˜์•ผ ํ•จ)
  • ํ™œ์šฉ : ์ตœ๋‹จ๊ฒฝ๋กœ ์ฐพ๊ธฐ, ์œ„์ƒ์ •๋ ฌ ๋“ฑ

BFS ๊ตฌํ˜„

void bfs(int start) {
    Queue<Integer> q = new LinkedList<>();
    q.offer(start);
    visited[start] = true;

    while (!q.isEmpty()) {
        int current = q.poll(); // ํ์—์„œ ๊บผ๋‚ธ๋‹ค
        if (current == target) { // ๋ชฉ์ ์ง€์ธ๊ฐ€?
            System.out.println("๋ชฉ์ ์ง€์ž…๋‹ˆ๋‹ค.");
            return;
        }
        for (int next : graph[current]) { // ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ณณ์„ ์ˆœํšŒ
            if (!visited[next]) { // ๊ฐˆ ์ˆ˜ ์žˆ๋Š”๊ฐ€?
                visited[next] = true; // ์ฒดํฌ์ธ
                q.offer(next); // ํ์— ๋„ฃ๋Š”๋‹ค
            }
        }
    }
}

์ˆœ์—ด, ์กฐํ•ฉ, ๋ถ€๋ถ„์ง‘ํ•ฉ

์ˆœ์—ด

  • ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒƒ๋“ค ์ค‘ ๋ช‡ ๊ฐœ๋ฅผ ๋ฝ‘์•„์„œ ํ•œ ์ค„๋กœ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ
  • ์„œ๋กœ ๋‹ค๋ฅธ n๊ฐœ ์ค‘ r๊ฐœ๋ฅผ ํƒํ•˜๋Š” ์ˆœ์—ด nPr = n * (n-1) * (n-2) * ... * (n-r+1)
  • nPn = n! ์ด๋ฉฐ 10! ์ด์ƒ์˜ ๊ณ„์‚ฐ์€ ์œ„ํ—˜ํ•˜๋‹ค.

์ˆœ์—ด ๊ตฌํ˜„ : ์žฌ๊ท€ ํ•จ์ˆ˜, ๋น„ํŠธ๋งˆ์Šคํฌ, next permutation

public class PermutationTest {

    static int N;
    static int[] input, result;
    static boolean[] isSelected;

    public static void main(String[] args) {

        N = 5; // N ์ดˆ๊ธฐํ™”
        input = new int[N]; // ์ž…๋ ฅ ๋ฐ›์€ ์ˆซ์ž ๋ฐฐ์—ด
        result = new int[N]; // ์ˆœ์—ด ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•  ๋ฐฐ์—ด
        isSelected = new boolean[N]; // ์„ ํƒ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•  ๋ฐฐ์—ด

        for (int i = 0; i < N; i++) {
            input[i] = i; // input ๋ฐฐ์—ด ์ดˆ๊ธฐํ™”
        }

        System.out.println("Permutation Recursive");
        recursive(0);

        System.out.println("Permutation Bitmask");
        bitmask(0, 0);

        System.out.println("Permutation Next Permutation");
        Arrays.sort(input); // ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌํ•˜์—ฌ ๊ฐ€์žฅ ์ž‘์€ ์ˆœ์—ด์˜ ํ˜•ํƒœ๋กœ ๋งŒ๋“ฆ
        do {
            System.out.println(Arrays.toString(input));
        } while (np());
    }

    // ์žฌ๊ท€ ํ•จ์ˆ˜
    private static void recursive(int cnt) {
        if (cnt == N) {
            System.out.println(Arrays.toString(result));
            return;
        }

        for (int i = 0; i < N; i++) {
            if (isSelected[i]) continue;

            result[cnt] = input[i];
            isSelected[i] = true;
            recursive(cnt+1);
            isSelected[i] = false;
        }
    }

    // ๋น„ํŠธ๋งˆ์Šคํฌ
    private static void bitmask(int cnt, int flag) {
        if (cnt == N) {
            System.out.println(Arrays.toString(result));
            return;
        }

        for (int i = 0; i < N; i++) {
            if ((flag & 1<<i) != 0) continue;

            result[cnt] = input[i];
            bitmask(cnt+1, flag | 1<<i);
        }
    }

    // next permutation
    private static boolean np() {
        int i = N-1;
        while (i > 0 && input[i-1] >= input[i]) --i;

        // ๋”์ด์ƒ ์•ž์ž๋ฆฌ๊ฐ€ ์—†๋Š” ์ƒํ™ฉ : ํ˜„ ์ˆœ์—ด์˜ ์ƒํƒœ๊ฐ€ ๊ฐ€์žฅ ํฐ ์ˆœ์—ด (๋งˆ์ง€๋ง‰ ์ˆœ์—ด)
        if (i == 0) return false;

        int j = N-1;
        while (input[i-1] >= input[j]) --j; // i-1๋ณด๋‹ค ํฐ ๊ฐ’์€ ๋ฌด์กฐ๊ฑด ์žˆ์Œ (์ ์–ด๋„ i)

        swap(i-1, j);

        int k = N-1;
        while (i < k) {
            swap(i++, k--);
        }

        return true;
    }

    private static void swap(int i, int j) {
        int temp = input[i];
        input[i] = input[j];
        input[j] = temp;
    }
}

์กฐํ•ฉ

  • ์„œ๋กœ ๋‹ค๋ฅธ n๊ฐœ์˜ ์›์†Œ ์ค‘ r๊ฐœ๋ฅผ ์ˆœ์„œ ์—†์ด ๊ณจ๋ผ๋‚ธ ๊ฒƒ
  • ์„œ๋กœ ๋‹ค๋ฅธ n๊ฐœ ์ค‘ r๊ฐœ๋ฅผ ํƒํ•˜๋Š” ์กฐํ•ฉ nCr = n! / (n-r)!r!

์กฐํ•ฉ ๊ตฌํ˜„ : ์žฌ๊ท€ ํ•จ์ˆ˜, next permutation

public class CombinationTest {

    static int N, R;
    static int[] input, result, P;

    public static void main(String[] args) {

        N = 5; // N ์ดˆ๊ธฐํ™”
        R = 3;
        input = new int[N]; // ์ž…๋ ฅ ๋ฐ›์€ ์ˆซ์ž ๋ฐฐ์—ด
        result = new int[R]; // ์กฐํ•ฉ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•  ๋ฐฐ์—ด

        for (int i = 0; i < N; i++) {
            input[i] = i; // input ๋ฐฐ์—ด ์ดˆ๊ธฐํ™”
        }

        System.out.println("Combination Recursive");
        recursive(0, 0);

        System.out.println("Combination Next Permutation");
        P = new int[N]; // N ํฌ๊ธฐ์˜ flag ๋ฐฐ์—ด
        // ์›์†Œ ํฌ๊ธฐ์™€ ๊ฐ™์€ ํฌ๊ธฐ์˜ int ๋ฐฐ์—ด P๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋’ค์—์„œ r๊ฐœ๋ฅผ 1๋กœ ์ดˆ๊ธฐํ™”
        int cnt = 0;
        while (++cnt <= R) P[N-cnt] = 1;

        do {
            for (int i = 0; i < N; i++) {
                // P ๋ฐฐ์—ด์—์„œ 0์ด ์•„๋‹Œ ๊ฐ’์„ ๊ฐ–๊ณ  ์žˆ๋Š” ์œ„์น˜์— ํ•ด๋‹นํ•˜๋Š” ์›์†Œ๊ฐ€ ์กฐํ•ฉ์— ์„ ํƒ๋œ ๊ฒƒ
                if (P[i] == 1) System.out.print(input[i] + " ");
            }
            System.out.println();
        } while (np());
    }

    private static void recursive(int cnt, int start) {
        if (cnt == R) {
            System.out.println(Arrays.toString(result));
            return;
        }

        for (int i = start; i < N; i++) {
            result[cnt] = input[i];
            recursive(cnt+1, i+1);
        }
    }

    private static boolean np() {
        // STEP 1
        int i = N-1;
        while (i > 0 && P[i-1] >= P[i]) --i;

        if (i == 0) return false;

        // STEP 2
        int j = N-1;
        while (P[i-1] >= P[j]) --j;

        // STEP 3
        swap(i-1, j);

        // STEP 4
        int k = N-1;
        while (i < k) {
            swap(i++, k--);
        }

        return true;
    }

    private static void swap(int i, int j) {
        int temp = P[i];
        P[i] = P[j];
        P[j] = temp;
    }
}

๋ถ€๋ถ„์ง‘ํ•ฉ

  • ์ง‘ํ•ฉ์— ํฌํ•จ๋œ ์›์†Œ๋“ค์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ
  • ์ง‘ํ•ฉ์˜ ์›์†Œ๊ฐ€ n๊ฐœ์ผ ๋•Œ, ๊ณต์ง‘ํ•ฉ์„ ํฌํ•จํ•œ ๋ถ€๋ถ„์ง‘ํ•ฉ(๋ฉฑ์ง‘ํ•ฉ, power set)์˜ ๊ฐœ์ˆ˜๋Š” 2N๊ฐœ์ด๋‹ค. (๊ฐ ์›์†Œ๋ฅผ ํฌํ•จ์‹œํ‚ค๊ฑฐ๋‚˜ / ํฌํ•จ์‹œํ‚ค์ง€ ์•Š๊ฑฐ๋‚˜)

๋ถ€๋ถ„์ง‘ํ•ฉ ๊ตฌํ˜„ : ์žฌ๊ท€ ํ•จ์ˆ˜, ๋ฐ”์ด๋„ˆ๋ฆฌ ์นด์šดํŒ…

public class SubsetTest {

    static int N;
    static int[] input;
    static boolean[] isSelected;

    public static void main(String[] args) {

        N = 3; // N ์ดˆ๊ธฐํ™”
        input = new int[N]; // ์ž…๋ ฅ ๋ฐ›์€ ์ˆซ์ž ๋ฐฐ์—ด
        isSelected = new boolean[N]; // ์„ ํƒ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•  ๋ฐฐ์—ด

        for (int i = 0; i < N; i++) {
            input[i] = i; // input ๋ฐฐ์—ด ์ดˆ๊ธฐํ™”
        }

        System.out.println("Subset Recursive");
        recursive(0);

        System.out.println("Subset Binary Counting");
        binaryCounting(1<<N); // 2^N
    }

    private static void recursive(int cnt) {
        if (cnt == N) {
            for (int i = 0; i < N; i++) {
                System.out.print( (isSelected[i] ? input[i] : "X") + " ");
            }
            System.out.println();
            return;
        }

        // ์„ ํƒ
        isSelected[cnt] = true;
        recursive(cnt+1);
        // ๋น„์„ ํƒ
        isSelected[cnt] = false;
        recursive(cnt+1);
    }

    private static void binaryCounting(int caseCount) {

        for (int flag = 0; flag < caseCount; flag++) { // flag : ๋น„ํŠธ๋งˆ์Šคํฌ๋˜์–ด ์žˆ๋Š” ์ˆ˜
            for (int j = 0; j < N; j++) {
                if ((flag & 1<<j) != 0) {
                    System.out.print(input[j] + " ");
                } else {
                    System.out.print("X ");
                }
            }
            System.out.println();
        }
    }
}

๋ฐฑํŠธ๋ž˜ํ‚น (Backtracking)

๋ฐฑํŠธ๋ž˜ํ‚น์€ DFS ๋ฌธ์ œ์—์„œ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•  ํ•„์š”๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ์ ์šฉํ•œ๋‹ค. ๋‹ค์‹œ ๋งํ•ด, ๋ฃจํŠธ ๋…ธ๋“œ์—์„œ ๋ฆฌํ”„ ๋…ธ๋“œ๊นŒ์ง€์˜ ๊ฒฝ๋กœ๋Š” ํ•ด๋‹ต ํ›„๋ณด(candidate solution)๊ฐ€ ๋˜๋Š”๋ฐ ์ด ๋•Œ ๋ชจ๋“  ํ›„๋ณด๋ฅผ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๊ณ  ํ›„๋ณด๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ํŒ๋‹จ๋˜๋ฉด ๋” ์ด์ƒ ๊ฒ€์ƒ‰ํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋ฐฑํŠธ๋ž˜ํ‚น ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ์œ ๋ง(promising)ํ•˜๋‹ค : ์–ด๋–ค ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•˜์˜€์„ ๋•Œ ๊ทธ ๋…ธ๋“œ๋ฅผ ํฌํ•จํ•œ ๊ฒฝ๋กœ๊ฐ€ ํ•ด๋‹ต์ด ๋  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ€์ง€์น˜๊ธฐ(pruning) : ์œ ๋งํ•˜์ง€ ์•Š์€ ๋…ธ๋“œ๊ฐ€ ํฌํ•จ๋˜๋Š” ๊ฒฝ๋กœ๋Š” ๋” ์ด์ƒ ๊ณ ๋ คํ•˜์ง€ ์•Š๋Š”๋‹ค.
  1. ์ƒํƒœ ๊ณต๊ฐ„ ํŠธ๋ฆฌ์˜ ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰(DFS)์„ ์‹ค์‹œํ•œ๋‹ค.
  2. ๊ฐ ๋…ธ๋“œ๊ฐ€ ์œ ๋ง(promising)ํ•œ์ง€๋ฅผ ์ ๊ฒ€ํ•œ๋‹ค.
  3. ๋งŒ์ผ ๊ทธ ๋…ธ๋“œ๊ฐ€ ์œ ๋ง(promising)ํ•˜์ง€ ์•Š์œผ๋ฉด, ๊ทธ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ๋กœ ๋˜๋Œ์•„๊ฐ€(backtracking) ๋‹ค์Œ ์ž์‹ ๋…ธ๋“œ๋กœ์˜ ๊ฒ€์ƒ‰์„ ๊ณ„์†ํ•œ๋‹ค.

๋ฐฑํŠธ๋ž˜ํ‚น์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ€์ง€์น˜๊ธฐ(pruning) ๋ฅผ ํ†ตํ•ด ๋ถˆํ•„์š”ํ•œ ๊ฒฝ๋กœ๋ฅผ ์ฐจ๋‹จํ•˜์—ฌ ์™„์ „ํƒ์ƒ‰(DFS)๋ณด๋‹ค ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ํ›จ์”ฌ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ N-Queen ๋ฌธ์ œ๊ฐ€ ๋ฐฑํŠธ๋ž˜ํ‚น์˜ ์ข‹์€ ์˜ˆ์‹œ์ด๋‹ค.

N-Queen

N-Queen ๋ฌธ์ œ๋Š” N*N ์ฒด์ŠคํŒ์— ํ€ธ N๊ฐœ๋ฅผ ์„œ๋กœ ๊ณต๊ฒฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋†“๋Š” ๋ฌธ์ œ๋ฅผ ๋งํ•œ๋‹ค. ๋ฐฑํŠธ๋ž˜ํ‚น ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด N-Queen์„ ํ•ด๊ฒฐํ•˜๋Š” ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.

BOJ 9663 ๋ฌธ์ œ๋ฅผ ์˜ˆ์‹œ๋กœ ๋“ค์–ด ์„ค๋ช…์„ ํ•ด๋ณด๊ฒ ๋‹ค.

์„œ๋กœ ๊ณต๊ฒฉํ•  ์ˆ˜ ์—†๋„๋ก ํ€ธ์„ ๋†“๋Š” ๋ฐฉ๋ฒ•์˜ ์ˆ˜๋ฅผ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค.

์œ„์™€ ๊ฐ™์ด ๋ฐฐ์น˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์ •๋‹ต์ด ๋œ๋‹ค.

๋ฐฑํŠธ๋ž˜ํ‚น์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด N๊ฐœ์˜ ํ€ธ์„ ๋†“์„ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ์‹œ๋„ํ•ด๋ณธ ๋’ค ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋Š” ์ง€๋ฅผ ์ฒดํฌํ•ด๋ณด๋ฉด ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ์™„์ „ํƒ์ƒ‰ ๋ฐฉ์‹์€ ์—„์ฒญ๋‚˜๊ฒŒ ํฐ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ–๋Š”๋‹ค. ๋ชจ๋“  ๋…ธ๋“œ์— ํ€ธ์„ ๋†“์•„๋ณด๋Š” ๊ฒฝ์šฐ์˜ ์ˆ˜ n*nCn, ๋Œ€๊ฐ์„ /์ˆ˜์ง/์ˆ˜ํ‰์— ํ€ธ์ด ์žˆ๋Š”์ง€ ํŒ๋‹จํ•˜๋Š”๋ฐ O(N^2)์ด๋‹ˆ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ ํ„ฐ๋ฌด๋‹ˆ ์—†์ด ์ปค์ง์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

n๊ฐ’์ด 10๋งŒ ๋˜์–ด๋„ 17,310,309,456,440 ๊ฐœ์˜ ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๊ฐ–๋Š”๋‹ค.

N์ด ์ปค์งˆ์ˆ˜๋ก ์‹œ๊ฐ„๋ณต์žก๋„ ์—ญ์‹œ ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ์ฆ๊ฐ€ํ•˜๋ฏ€๋กœ ๋„ˆ๋ฌด๋‚˜ ๋น„ํšจ์œจ์ ์ด๋‹ค. ์ด๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฑํŠธ๋ž˜ํ‚น ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•œ๋‹ค.

๋จผ์ € ํ€ธ์˜ ํŠน์„ฑ์„ ์ƒ๊ฐํ•ด๋ณด์ž.

  1. ํ€ธ์€ ์ˆ˜์ง์„ ์ƒ์— ์žˆ๋Š” ๋ง์„ ๊ณต๊ฒฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ํ€ธ์€ ์ˆ˜ํ‰์„ ์ƒ์— ์žˆ๋Š” ๋ง์„ ๊ณต๊ฒฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. ํ€ธ์€ ๋Œ€๊ฐ์„ ์ƒ์— ์žˆ๋Š” ๋ง์„ ๊ณต๊ฒฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ํŠน์„ฑ์„ ํ†ตํ•ด ์šฐ๋ฆฌ๋Š” ํ€ธ์„ ๋†“์„ ์ˆ˜ ์—†๋Š” ์ž๋ฆฌ์— ๋Œ€ํ•ด ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ํ€ธ์€ ํ•œ row์— ํ•˜๋‚˜๋งŒ ๋‘˜ ์ˆ˜ ์žˆ๋‹ค.
  2. ํ€ธ์€ ํ•œ column์— ํ•˜๋‚˜๋งŒ ๋‘˜ ์ˆ˜ ์žˆ๋‹ค.
  3. ๋Œ€๊ฐ์„ ์— ํ€ธ์ด ์žˆ๋‹ค๋ฉด ๋‘˜ ์ˆ˜ ์—†๋‹ค.

์ด ๊ณผ์ •์ด ์œ ๋ง์„ฑ ํŒ๋‹จ๊ณผ ๊ฐ€์ง€์น˜๊ธฐ ์— ํ•ด๋‹น๋œ๋‹ค

์œ ๋ง์„ฑ ํŒ๋‹จ ์กฐ๊ฑด1, 2์— ์˜ํ•ด 2์ฐจ์› ์ฒด์ŠคํŒ์—์„œ ๋ชจ๋“  ์œ„์น˜๋ฅผ ์‚ดํ•„ ํ•„์š” ์—†์ด ํ–‰ ํ˜น์€ ์—ด ๋‹จ์œ„๋กœ ํ™•์ธํ•˜๋ฉด ๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

ํ–‰ ๋‹จ์œ„๋กœ ๋ง์„ ๋†“์œผ๋ฉฐ ๋ชจ๋“  ํ–‰์— ํ•˜๋‚˜์”ฉ ํ€ธ์„ ๋ฐฐ์น˜ํ•˜๋„๋ก ํ•˜๋Š” ๋ฐฑํŠธ๋ž˜ํ‚น ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ด๋ณด์ž.

int board[N]; // ๊ฐ ํ–‰์— ๋Œ€ํ•ด ํ€ธ์ด ์œ„์น˜ํ•œ ์—ด์˜ ๋ฒˆํ˜ธ๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๋ฐฐ์—ด.

void bt(int rowNum) {
    if (rowNum == N) { // ๋ชจ๋“  ํ–‰์— ๋ง์„ ๋‹ค ๋†“์•˜๋‹ค๋ฉด ์ •๋‹ต ๊ฐœ์ˆ˜๋ฅผ ํ•˜๋‚˜ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
        answer++;
        return;
    }

    for (int colNum = 0; colNum < N; colNum++) {
    // ๊ฐ ์—ด์— ๋Œ€ํ•ด ํ€ธ์„ ๋†“์„ ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
        if (isPromissing(rowNum, colNum)) {
            board[rowNum] = colNum; // rowNum ํ–‰์˜ colNum ์—ด์— ํ€ธ์„ ๋ฐฐ์น˜ํ•œ๋‹ค.
            bt(rowNum + 1); // ์—ด์˜ ๋ฒˆํ˜ธ๋ฅผ ํ•˜๋‚˜ ์ฆ๊ฐ€์‹œํ‚ค๋ฉฐ ์žฌ๊ท€ ํ˜ธ์ถœํ•œ๋‹ค.
            board[rowNum] = 0;
        }
    }
}

์ด์ œ ์œ ๋ง์„ฑ์„ ํŒ๋‹จํ•˜๋Š” isPromissing ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ด๋ณด์ž.

์œ„์˜ ํ•จ์ˆ˜์— ๋”ฐ๋ผ ํ•˜๋‚˜์˜ ํ–‰์—๋Š” ํ•˜๋‚˜์˜ ํ€ธ๋งŒ ๋ฐฐ์น˜๋˜๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋˜๋ฏ€๋กœ ํ™•์ธํ•ด์•ผํ•˜๋Š” ๊ฒƒ์€ ๋‘๊ฐ€์ง€์ด๋‹ค.

  1. ๋Œ€๊ฐ์„  ์œ„์น˜์— ํ€ธ์ด ์กด์žฌํ•˜๋Š”๊ฐ€
  2. ๊ฐ™์€ ์—ด์— ํ€ธ์ด ์กด์žฌํ•˜๋Š”๊ฐ€
bool isPromising(int currentRow, int colNum) {
    for (int rowNum = 0; rowNum < currentRow; rowNum++) {
        if (board[rowNum] == colNum) return false;
        if (currentRow - rowNum == abs(colNum - board[rowNum])) return false;
    }
    return true;
}

ํ˜„์žฌ ํ€ธ์„ ๋†“์„ ์ˆ˜ ์žˆ๋ƒ ์—†๋ƒ๋ฅผ ํŒ๋‹จํ•˜๊ณ ์ž ํ•˜๋Š” ์œ„์น˜๋Š” colNum ํ–‰์˜ currentRow ์—ด์ด๋‹ค.

ํ•ด๋‹น ์œ„์น˜์˜ ๋Œ€๊ฐ์„ ์— ์žˆ๋Š” ๋…ธ๋“œ๋ž€?

(x,y)์™€ ๋Œ€๊ฐ์„ ์— ์œ„์น˜ํ•œ ๋…ธ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • (x+1, y+1), (x+2, y+2), (x+3, y+3) ...
  • (x-1, y-1), (x-2, y-2), (x-3, y-3) ...

์ฆ‰, ํ–‰ ๋ฒˆํ˜ธ๊ฐ„ ์ฐจ์ด์™€ ์—ด ๋ฒˆํ˜ธ๊ฐ„ ์ฐจ์ด์˜ ๊ฐ’์ด ๊ฐ™์€ ๋…ธ๋“œ๊ฐ€ ๋Œ€๊ฐ์„ ์— ์žˆ๋Š” ๋…ธ๋“œ๋ผ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. (isPromising ํ•จ์ˆ˜์˜ ๋‘๋ฒˆ์งธ ์กฐ๊ฑด๋ฌธ)

if (currentRow - rowNum == abs(colNum - board[rowNum]))

๋ถ„ํ•  ์ •๋ณต๋ฒ• (Divide and Conquer)

๋ถ„ํ•  ์ •๋ณต๋ฒ•์€ ์ „์ฒด ๋ฌธ์ œ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ถ€๋ถ„ ๋ฌธ์ œ๋“ค๋กœ ๋ถ„ํ•  ๊ฐ ๋ถ€๋ถ„ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐ(์ •๋ณต)ํ•จ์„ ํ†ตํ•ด ์ „์ฒด ๋ฌธ์ œ์˜ ํ•ด๋‹ต์„ ๋„์ถœํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ด๋Š” Top-down approach๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  • ๋ถ„ํ•  (Divide) : ํ•ด๊ฒฐํ•  ๋ฌธ์ œ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ๋ถ€๋ถ„์œผ๋กœ (์ถฉ๋ถ„ํžˆ ์ž‘์•„์„œ ํ•ด๊ฒฐํ•˜๊ธฐ ์‰ฌ์šธ ๋•Œ๊นŒ์ง€) ๋‚˜๋ˆˆ๋‹ค.
  • ์ •๋ณต (Conquer) : ๋‚˜๋ˆˆ ๋ถ€๋ถ„ ๋ฌธ์ œ๋ฅผ ๊ฐ๊ฐ ํ•ด๊ฒฐํ•œ๋‹ค.
  • ํ†ตํ•ฉ (Combine) : ๊ฐ ๋ถ€๋ถ„ ๋ฌธ์ œ์˜ ํ•ด๋‹ต์„ ๋ชจ์•„์„œ ์ „์ฒด ๋ฌธ์ œ์˜ ํ•ด๋‹ต์„ ๋„์ถœํ•œ๋‹ค.

์ด๋ถ„ ํƒ์ƒ‰ (Binary Search)

์ด๋ถ„ ํƒ์ƒ‰ ์ง„ํ–‰์„ ์œ„ํ•ด์„œ๋Š” ์ž๋ฃŒ๊ฐ€ ์ •๋ ฌ๋œ ์ƒํƒœ์—ฌ์•ผ ํ•œ๋‹ค.

์ •๋ ฌ๋œ ๋ฐฐ์—ด์—์„œ ํŠน์ • ๊ฐ’ X๋ฅผ ์ฐพ๊ณ ์ž ํ•  ๋•Œ, ์ด๋ถ„ ํƒ์ƒ‰์„ ์ด์šฉํ•˜๋ฉด ํ›จ์”ฌ ๋น ๋ฅด๊ฒŒ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Divide : ๋ฐฐ์—ด์„ ๋‘ ๊ฐœ์˜ ๋ถ€๋ถ„ ๋ฐฐ์—ด๋กœ ๋‚˜๋ˆˆ๋‹ค. X๊ฐ€ ๊ฐ€์šด๋ฐ์— ์žˆ๋Š” ๊ฐ’๋ณด๋‹ค ์ž‘์œผ๋ฉด ์™ผ์ชฝ ๋ถ€๋ถ„ ๋ฐฐ์—ด์„, ํฌ๋ฉด ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„ ๋ฐฐ์—ด์„ ์„ ํƒํ•œ๋‹ค.
  • Conquer : ๋ฐฐ์—ด์˜ ๊ฐ€์šด๋ฐ ๊ฐ’์ด X์™€ ๊ฐ™์€์ง€ ๋น„๊ตํ•œ๋‹ค. ๊ฐ™์ง€ ์•Š๋‹ค๋ฉด Divide ๊ณผ์ •์„ ์žฌ๊ท€์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • Combine : ๋ถ€๋ถ„ ๋ฐฐ์—ด์—์„œ ์ฐพ์€ ๋‹ต์ด ๊ณง ์ „์ฒด ํ•ด๋‹ต์ด๋‹ค.

์ด ์™ธ์—๋„ ๋ถ„ํ•  ์ •๋ณต๋ฒ•์„ ํ†ตํ•ด MergeSort, QuickSort์˜ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฑฐ๋“ญ์ œ๊ณฑ์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌํ•  ๋•Œ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•(2^8 -> 2๋ฅผ 8๋ฒˆ ๊ณฑํ•˜๊ธฐ vs ((2^2)^2)^2)์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ๊ธฐ๋„ ํ•˜๋‹ค.


ํƒ์š• ์•Œ๊ณ ๋ฆฌ์ฆ˜ (Greedy)

์ž์„ธํ•œ ์„ค๋ช… - ์ž‘์„ฑ์ž ์žฅ์ฃผ์„ญ | Greedy Algorithm

ํƒ์š• ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ตœ์ ํ•ด๋ฅผ ๊ตฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ทผ์‹œ์•ˆ์ ์ธ ๋ฐฉ๋ฒ•์ด๋‹ค. ์ตœ์ ํ™” ๋ฌธ์ œ(optimization)๋ž€ ๊ฐ€๋Šฅํ•œ ํ•ด๋“ค ์ค‘์—์„œ ๊ฐ€์žฅ ์ข‹์€ ํ•ด๋ฅผ ์ฐพ๋Š” ๋ฌธ์ œ์ด๋‹ค. Greedyํ•œ ์ ‘๊ทผ์€ ์‚ฌ๋žŒ์˜ ์ƒ๊ฐ๊ณผ ๋‹ฎ์•„ ์žˆ๋‹ค. ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ๋•Œ๋งˆ๋‹ค ๊ทธ ์ˆœ๊ฐ„์— ์ตœ์ ์ด๋ผ๊ณ  ์ƒ๊ฐ๋˜๋Š” ๊ฒƒ์„ ์„ ํƒํ•˜๋ฉฐ, ํ•œ๋ฒˆ ์„ ํƒ๋œ ๊ฒƒ์€ ๋ฒˆ๋ณตํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜์—ฌ ์ตœ์ข…์ ์ธ ํ•ด๋‹ต์— ๋„๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค. ๋‹จ, ์ตœ์ ํ•ด๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ•œ๋‹ค๋Š” ๋ณด์žฅ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ฆ๋ช… ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค.

์ตœ์ ํ•ด๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ•œ๋‹ค๋Š” ๋ณด์žฅ์ด ์—†๋‹ค.

์ตœ์†Œ์˜ ๋™์ „์œผ๋กœ 800์›์„ ๋งŒ๋“ค๊ณ ์ž ํ•  ๋•Œ, Greedyํ•œ ์ ‘๊ทผ์œผ๋กœ๋Š” ํฐ ๋™์ „๋ถ€ํ„ฐ ์„ ํƒํ•˜๋ฉด ๋  ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋žฌ์„ ๋•Œ ์ตœ์ ํ•ด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค.

  • ๋™์ „ ์ข…๋ฅ˜๊ฐ€ 500, 100, 50, 10์ผ ๊ฒฝ์šฐ : 500์› 1๊ฐœ, 100์› 3๊ฐœ
  • ๋™์ „ ์ข…๋ฅ˜๊ฐ€ 500, 400, 100, 50, 10์ผ ๊ฒฝ์šฐ : 500์› 1๊ฐœ, 100์› 3๊ฐœ > 400์› 2๊ฐœ

ํƒ์š• ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜ ๋‘ ๊ฐ€์ง€ ์†์„ฑ์„ ๋งŒ์กฑํ•จ์„ ์ฆ๋ช…ํ•ด์•ผ ํ•œ๋‹ค.

  • ํƒ์š•์  ์„ ํƒ ์†์„ฑ (greedy choice property) : ํƒ์š•์ ์œผ๋กœ๋งŒ ์„ ํƒ์„ ํ•ด๋„ ์ตœ์ ํ•ด๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ตœ์  ๋ถ€๋ถ„ ๊ตฌ์กฐ (optimal substructure property) : ๋ถ€๋ถ„ ๋ฌธ์ œ์˜ ์ตœ์ ํ•ด์—์„œ ์ „์ฒด ๋ฌธ์ œ์˜ ์ตœ์ ํ•ด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๋Œ€ํ‘œ์ ์ธ ํƒ์š• ๊ธฐ๋ฒ•์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ํ”„๋ฆผ(Prim) ์•Œ๊ณ ๋ฆฌ์ฆ˜ : ํ˜„์žฌ ์ •์ ์— ์—ฐ๊ฒฐ๋œ ๊ฐ„์„ ๋“ค ์ค‘ ๊ฐ€์ค‘์น˜๊ฐ€ ์ž‘์€ ๊ฐ„์„ ๋ถ€ํ„ฐ ์„ ํƒํ•œ๋‹ค.
  • ํฌ๋ฃจ์Šค์นผ(Kruskal) ์•Œ๊ณ ๋ฆฌ์ฆ˜ : ๊ฐ ๋‹จ๊ณ„์—์„œ ๊ฐ€์ค‘์น˜๊ฐ€ ์ž‘์€ ๊ฐ„์„ ๋ถ€ํ„ฐ ์„ ํƒํ•œ๋‹ค.
  • ๋‹ค์ต์ŠคํŠธ๋ผ(Dijkstra) ์•Œ๊ณ ๋ฆฌ์ฆ˜ : ํ˜„์žฌ ์ •์ ์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ •์ ์„ ์„ ํƒํ•œ๋‹ค.

๋™์  ๊ณ„ํš๋ฒ• (Dynamic Programming)

๋™์  ๊ณ„ํš๋ฒ•์€ ์ฃผ์–ด์ง„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ•˜์œ„ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆ„์–ด ํ‘ผ ๋‹ค์Œ ๊ฒฐํ•ฉํ•˜์—ฌ ๋‹ต์„ ์ฐพ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ์œ„ํ•ด์„œ๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•˜์œ„ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆ„์–ด ๋ณด๊ณ  ์ฃผ์–ด์ง„ ์‹œ๊ฐ„ ๋ณต์žก๋„ ๋‚ด์—์„œ ์ˆ˜ํ–‰์ด ๊ฐ€๋Šฅํ•œ ์ตœ์ ์˜ ์ ํ™”์‹์„ ์ฐพ๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ด๋‹ค.

๋™์  ๊ณ„ํš๋ฒ•์„ ์ ์šฉํ•œ ๋Œ€ํ‘œ์ ์ธ ๋ฌธ์ œ๋กœ๋Š” ๋ฐฐ๋‚ญ ์ง์‹ธ๊ธฐ ๋ฌธ์ œ(Knapsack Problem), ์ตœ์žฅ์ฆ๊ฐ€์ˆ˜์—ด(LIS, Longest Increasing Subsequence), ์™ธํŒ์› ์ˆœํšŒ ๋ฌธ์ œ(TSP, Traveling Salesman Problem) ๋“ฑ์ด ์žˆ๋‹ค. ์ด ๋ฐ–์—๋„ memoization ๋ฐ ์ ํ™”์‹์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๋ฅผ ํ›จ์”ฌ ํšจ์œจ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

"ํฐ ๋ฌธ์ œ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ•˜์œ„ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆ„์–ด ํ‘ผ๋‹ค" ๋ผ๋Š” ์ ์—์„œ DP๋Š” ๊ทธ ํ•˜์œ„์˜ ๊ฐ’์ด ๊ณ„์† ๋ณ€ํ•˜๊ณ , DAC๋Š” ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ฐจ์ด์ ์ด ์žˆ๋‹ค.

0-1 Knapsack

Knapsack ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํฌ๊ฒŒ ๋‘๊ฐ€์ง€๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

  1. Fractional Knapsack
  2. 0-1 Knapsack

Fractional Knapsack์˜ ๊ฒฝ์šฐ ํƒ์š• ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋ฉด 0-1 Knapsack์˜ ๊ฒฝ์šฐ ํƒ์š• ๊ธฐ๋ฒ•์„ ํ†ตํ•ด์„œ๋Š” ์ •ํ•ด๋ฅผ ๋ณด์žฅํ•  ์ˆ˜ ์—†๊ณ  ๋™์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์‚ฌ์šฉํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

0-1 Knapsack ์ด๋ž€ ?

  1. N๊ฐœ์˜ ๋ณด์„์ด ์žˆ๋‹ค.
  2. ๋ณด์„๋“ค์€ ๊ฐ ๋ณด์„๋งˆ๋‹ค ๊ฐ€๊ฒฉ(V)๊ณผ ๋ฌด๊ฒŒ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
  3. ๋„๋‘‘์ด ๋ณด์„์„ ํ›”์น˜๋ ค๊ณ  ํ•œ๋‹ค! ํ•˜์ง€๋งŒ ๋„๋‘‘์˜ ๊ฐ€๋ฐฉ์—๋Š” ์ •ํ•ด์ง„ ๋ฌด๊ฒŒ(W) ๋ฐ‘์œผ๋กœ๋งŒ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.
  4. ๋„๋‘‘์ด ๋ฐฐ๋‚ญ ์•ˆ์— ๋‹ด์€ ๋ณด์„์˜ ๊ฐ€๊ฒฉ์˜ ํ•ฉ์ด ์ตœ๋Œ€๊ฐ€ ๋˜๋„๋ก ํ•˜๋ผ.

๋™์  ๊ณ„ํš๋ฒ•์˜ ๊ธฐ๋ณธ์ ์ธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์˜ํ•ด, ์ด์ „ ๋‹จ๊ณ„์—์„œ ๊ตฌํ–ˆ๋˜ ์ตœ์ ํ•ด๊ฐ€ ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ์ตœ์ ํ•ด๋ฅผ ๊ตฌํ•˜๋Š”๋ฐ ํฌํ•จ๋จ์„ ๊ธฐ์–ตํ•˜๋ฉฐ ์ ํ™”์‹์„ ์„ค๊ณ„ํ•ด๋ณด์ž.

KNAPSACK(i, w) : 1~i ๋ฒˆํ˜ธ๊นŒ์ง€์˜ ๋ณด์„ ์ค‘ ๋ฐฐ๋‚ญ์˜ ์ตœ๋Œ€ ๋ฌด๊ฒŒ๊ฐ€ w์ผ ๋•Œ์˜ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€์˜ ๋ณด์„๊ฐ€๊ฒฉํ•ฉ.

์ด๋Ÿฌํ•œ ์‹์„ ์„ค๊ณ„ํ•œ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ, ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ์ตœ์ ํ•ด๋Š” KNAPSACK(N, W)๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค.

๋ฐฐ๋‚ญ ๋ฌด๊ฒŒ๋ฅผ 1๋ถ€ํ„ฐ W๊นŒ์ง€ ๋Š˜๋ ค๊ฐ€๋ฉฐ, ๋ณด์„์„ ๋„ฃ๋Š”๋‹ค๊ณ  ํ•ด๋ณด์ž.

์ด ๋•Œ ๋‹ค์Œ ๋ณด์„์„ ๋„ฃ๊ธฐ ์ „ ๊ณ ๋ คํ•ด์•ผํ•  ๊ฒฝ์šฐ์˜ ์ˆ˜๊ฐ€ 3๊ฐ€์ง€ ์žˆ๋‹ค.

  1. ๋‹ค์Œ ๋ณด์„์„ ๋ฐฐ๋‚ญ์— ๋‹ด์„ ์ˆ˜ ์—†๋‹ค.

  2. ๋‹ค์Œ ๋ณด์„์„ ๋ฐฐ๋‚ญ์— ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.

    2-1. ๋‹ค๋ฅธ ๋ณด์„์„ ๋นผ๊ณ  ํ˜„์žฌ ๋ณด์„์„ ๋‹ด๋Š”๋‹ค.

    2-2. ๋‹ค๋ฅธ ๋ณด์„๊ณผ ํ•จ๊ป˜ ํ˜„์žฌ ๋ณด์„์„ ๋‹ด๋Š”๋‹ค.

๋ณด์„์„ ๋‹ด์„ ์ˆ˜ ์—†๋Š” ์กฐ๊ฑด์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. ํ˜„์žฌ ๋ณด์„์˜ ๋ฌด๊ฒŒ๊ฐ€ ๊ฐ€๋ฐฉ์˜ ๋ฌด๊ฒŒ๋ณด๋‹ค ๋ฌด๊ฒ๋‹ค.
  2. ๋‹ค๋ฅธ ๋ณด์„์„ ๋นผ๊ณ  ๋„ฃ์—ˆ์„ ๋•Œ ์ด์ „ ๋‹จ๊ณ„๋ณด๋‹ค ๋‚ฎ์€ ๊ฐ€์น˜๋ฅผ ๊ฐ€์ง„๋‹ค.

KNAPSACK(N, W)๋Š” ๊ฒฐ๊ตญ KNAPSACK(N-1, w)์™€ ์—ฐ๊ด€์„ ๊ฐ–๊ฒŒ ๋œ๋‹ค. ์ฆ‰, ์ด์ „ ๋ณด์„ ๋ฒˆํ˜ธ์˜ ์ตœ์ ํ•ด ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์œ„์˜ ์กฐ๊ฑด๋“ค์„ ๊ณ ๋ คํ•˜์—ฌ ์ ํ™”์‹์„ ์„ธ์›Œ๋ณผ ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

                 (if w[i] > w) KNAPSACK(i-1, w)
KNAPSACK(i, w) =
                 (if w[i] <= w) max(KNAPSACK(i-1, w), KNAPSACK(i-1, w-w[i]) + V[i])

์œ„์˜ ์ ํ™”์‹์„ ์‚ฌ์šฉํ•ด ๋ณด์„ ๋ฒˆํ˜ธ 1๋ถ€ํ„ฐ N๊นŒ์ง€, ๋ฐฐ๋‚ญ ๋ฌด๊ฒŒ๋ฅผ 1๋ถ€ํ„ฐ W๊นŒ์ง€ ๋ฐ˜๋ณตํ•˜๋ฉฐ ์ด์ฐจ์› ๋ฐฐ์—ด์„ ์ฑ„์›Œ๋‚˜๊ฐ€๋ฉด ๋œ๋‹ค.

์ด๋Ÿฌํ•œ ํ’€์ด๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ฐฐ๋‚ญ๋ฌธ์ œ๋ฅผ O(N*W)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋กœ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.