[BOJ] 15649~15652번 N과M - C++

"백트래킹"

Posted by Yongmin on May 31, 2021

문제

N과M(1)
N과M(2)
N과M(3)
N과M(4)

풀이

전형적인 백트래킹 문제라고 한다. 주어진 범위가 주어지면 순열과 조합을 찾는 문제로서, 재귀함수 호출을 이용한 풀이로 진행하였다. Iteration과 재귀함수 호출을 이용해 문제를 해결하는 부분이다. N과 M이 각각 4, 2라면 맨 처음 array에 [1]이 담겨있다가, function call로 인해 [1, 2]가 담기고, 그 이후 function call로 인해 그 arr가 print 된다. 그 후 return으로 인해 result.pop_back() 으로 인해 arr가 [1]이 되고 난 뒤, iteration이 진행되어 [1, 3]이 담기고 그 이후 function call로 인해 print가 되는 것을 반복하는 방식이다. 또 check array를 통해서 중복이 되는 것을 방지하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void DFS(int cnt){
    if(cnt == M){
        for(int i = 0; i<M; i++){
            printf("%d ", result[i]);
        }
        cout << "\n";
        return;
    }
    for(int i = 0;i<N;i++){
        if(check[i] == true) continue;
        else{
            check[i] = true;
            result.push_back(arr[i]);
            DFS(cnt+1);
            result.pop_back();
            check[i] = false;
        }
    }

소스 코드

조합문제이면서, 중복을 허용하지 않는 N과M(2) 문제의 소스코드이다. 1, 3, 4번 문제도 중복을 하냐, 시작점을 처음부터하는가 그 앞자리 수보다 큰 숫자로 하는가의 부분의 차이로 순열과 조합 문제 풀이가 가능하다.

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
#include <iostream>
#include <vector>
using namespace std;

int N, M;
vector<int> result;
int arr[8];
bool check[8];
bool start[8];

void combination(int start, int cont){
    
    if(cont == M){
        for(int i = 0; i<M; i++){
            printf("%d ", result[i]);
        }
        cout << "\n" ;
        return;
    }
    for(int i = start; i<N; i++){
        if(check[i] == true) continue;
        else{
            check[i] = true; // 중복을 피해주기 위함
            result.push_back(arr[i]);
            combination(i+1, cont+1); // 시작점을 키워서 조합 문제 풀이로 변경.
            result.pop_back();
            check[i] = false;
        }
    }
    
}

int main(){
    scanf("%d %d", &N, &M);
    for(int i = 0; i<N; i++){
        arr[i] = i+1;
    }
    
    combination(0, 0);
    
}


# # #