거북이의 IT 공부

[백준 15650] N과 M(2) - C++ / 백트래킹, 재귀 알고리즘 본문

Baekjoon

[백준 15650] N과 M(2) - C++ / 백트래킹, 재귀 알고리즘

버니빈 2020. 5. 15. 14:16

문제

https://www.acmicpc.net/problem/15650

 

15650번: N과 M (2)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

나의 코드

저번시간에는 재귀를 통한 '순열 구현'을 배웠다면

이번시간에는 재귀를 통한 '조합 구현'이다.

** 참고 사이트 : https://yabmoons.tistory.com/99

 

[ 순열과 조합 구현 ] - 재귀를 통한 구현(1 - 조합) (C++)

브루트포스 알고리즘에서 가장 많이 사용되는 방법이 순열과 조합등으로 모든 경우의 수를 모두 계산해본 뒤에 원하는 결과 값을 찾는 방식이다. 이 글에서는, 순열과 조합을 STL을 사용하지 않�

yabmoons.tistory.com

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#define MAX 8
 
using namespace std;
 
int arr[MAX];
bool visited[MAX];
int cnt, idx, n, m;
 
void Print() {
    for (int i = 0; i < n; i++)
        if (visited[i]) {
            cout << arr[i] << " ";
        }
    cout << '\n';
}
 
void DFS(int cnt, int idx) {
    if (cnt == m) {
        Print();
        return;
    }
 
    for (int i = idx; i < n; i++) {
        if (visited[i]) continue;
        visited[i] = true;
 
        DFS(cnt + 1, i + 1);
        visited[i] = false;
    }
}
 
int main(void) {
    cin >> n >> m;
 
    for (int i = 0; i < n; i++) {
        arr[i] = i + 1;
        visited[i] = false;
    }
 
    DFS(00);
}
cs

 

확실히 순열을 배우고 풀으닌깐 더 이해가 잘 되는 것 같다.

조합은 순열과 달리 중복되면 안되므로 idx(시작점)이 필요하다.

다음 cnt(count)로 넘어갈 때 이전에 건든 작은 숫자를 건들지 않도록 하기 위해 idx가 있는 것이다.

 

<입력>

4 2

 

<출력 결과>

1 2
1 3
1 4
2 3
2 4
3 4

 

<이해>
1. cnt = 0, idx = 0 , i = 0

visited = {1}  //앞으로 visited에는 true인 값을 표시한다(실제는 bool타입)

2. for문으로 들어가서 i = idx = 1부터 시작

cnt = 1, idx = 1, i = 1

visited = {1,2}

3. for문으로 들어가서 i = idx = 2부터 시작

cnt = 2, idx = 2, i =2

visited = {1,2,3}

4. cnt = 3 , 출력

 

5. DFS(cnt + 1, i + 1);로 돌아온다.

cnt = 2, idx = 2,  i = 2

visited[2] = false;

6. cnt = 2, i = 3 -> idx = 4(이때 idx는 중요하지 않는다)

visited = {1,2,4}

7. cnt = 3, 출력

 

8. DFS(cnt + 1, i + 1);로 돌아온다.

cnt = 2, idx = 2,  i = 3

visited[3] = false;

9. cnt = 2, i = 4 -> idx = 5

visited = {1,2,5}

10. cnt = 3, 출력

 

11. cnt = 2, idx = 2,  i = 4

   visited[4] = false;

   for문이 끝남!!!!!

 

12.  DFS(cnt + 1, i + 1);로 돌아온다.

    cnt = 1, idx = 1, i = 1

    visited[1] = false;

13. cnt = 1, i = 2

   visited = {1, 3}

   dfs(cnt = 2, idx = 3)  //문법상 맞지 않지만 이해를 위해 적음

14. for문으로 들어와서 i = idx = 3부터 시작

cnt = 2, idx = 3 , i =3

visited = {1,3,4}

 

 

그리고 1로 시작하는 수열이 끝나면

cnt = 0, idx = 0, i = 0 으로 돌아가서 

visited[0] = false;

 

cnt = 0, i = 1 

visited = {2}

dfs(cnt = 1, idx = 2)

Comments