거북이의 IT 공부
[백준 15649] N과 M(1) - C++ / 백트래킹, 재귀 알고리즘 본문
문제
https://www.acmicpc.net/problem/15649
15649번: N과 M (1)
한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해
www.acmicpc.net
백트래킹이란?
아래에 정리해 두었다!
백트래킹 (Backtracking) 알고리즘이란?
백트래킹이란? 해를 찾아가는 도중, 지금의 경로가 해가 될 것 같지 않으면 그 경로를 더이상 가지 않고 되돌아가는(Backtracking) 기법을 말한다. -> 반복문의 횟수를 줄여서 효율적이다!!! 좀더 정��
bunnnybin.tistory.com
순열구현 - 남의 코드로 공부해보기
수열 = 순열(순서가 있음), 조합(뽑기)
일단 백트래킹을 하기 전에 DFS를 구현하는 재귀함수를 공부할 필요가 있다.
"재귀를 통한 순열 구현"에 대해 공부해보자.
* 참고사이트 : https://yabmoons.tistory.com/100
[ 순열과 조합 구현 ] - 재귀를 통한 구현(2 - 순열) (C++)
이번 글은 저번 글에 이어서 순열에 대한 설명이다 ! ( 저번 글 바로가기 ) 기본적인 설명은 지난 글에서 모두 했으니 이번 글에서는 바로 순열 구현하는 것으로 들어가도록 하겠다. [ 구현방법 ]
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
|
#include <iostream>
#include<vector>
#define MAX 5
using namespace std;
int arr[MAX];
bool visited[MAX];
vector<int> vec;
void print() {
for (int i = 0; i < vec.size(); i++)
cout << vec[i] << " ";
cout << '\n';
}
void dfs(int cnt) { //cnt == count약자
if (cnt == 3) {
print();
return;
}
for (int i = 0; i < MAX; i++) {
if (visited[i] == true) continue;
visited[i] = true;
vec.push_back(arr[i]);
dfs(cnt + 1);
vec.pop_back();
visited[i] = false;
}
}
int main(void) {
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
dfs(0);
}
|
cs |
<출력결과>
1 2 3
1 2 4
1 2 5
1 3 2
1 3 4
1 3 5
1 4 2
1 4 3
1 4 5
1 5 2
1 5 3
1 5 4 .....
<이해>

1. cnt=0, i=0
arr = {1}
2. cnt = 1, i=0,1
arr = {1,2}
3. cnt = 2, i=0,1,2
arr = {1,2,3}
4. cnt = 3, 출력

5. "백트래킹"
cnt = 2, i = 2
vec.pop_back(), visited[2] = false
arr = {1, 2}
6. cnt = 2, i = 3
arr = { 1, 2, 4 }
7. cnt = 3, 출력
8. cnt = 2, i = 3
vec.pop_back(), visited[3] = false
arr = {1, 2}
9. cnt = 2, i = 4
arr = {1,2,5}
10. cnt = 3, 출력
-> cnt = 2, i = 4
vec.pop_back(), visited[4] = false

★★★★중요★★★★
11. for문 다 돌아서 cnt = 1, i = 1
vec.pop_back(), visited[1] = false

12. cnt = 1, i = 2
arr = {1, 3}
13. cnt = 2, i = 0, 1
arr = {1,3,2}
14. cnt = 2, i = 1
vec.pop_back(), visited[1] = false
15. cnt = 2, i = 2, 3
arr = {1,3,4}
이런 방식으로 dfs는 재귀로 돌아가고
재귀로 순열을 구할 수 있다.
정답 코드
이제는 순열 구현을 통해 백준 문제를 쉽게 풀 수 있다.
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
43
44
|
#include <iostream>
#include <vector>
# define MAX 8
using namespace std;
int arr[MAX]; //주어진 숫자
bool visited[MAX]; //방문, 중복 방지
vector<int> vec; //출력할 수열
int cnt, n, m;
void Print() {
for (int i = 0; i < vec.size(); i++)
cout << vec[i] << " ";
cout << '\n';
return;
}
void DFS(int cnt) {
if (cnt == m) {
Print();
return;
}
for (int i = 0; i < n; i++) {
if (visited[i]) continue;
visited[i] = true;
vec.push_back(arr[i]);
DFS(cnt + 1);
vec.pop_back();
visited[i] = false;
}
}
int main(void) {
cin >> n >> m;
for (int i = 0; i < n; i++) {
arr[i] = i + 1;
visited[i] = false;
}
DFS(0);
}
|
cs |
'Baekjoon' 카테고리의 다른 글
[백준 15652] N과 M(4) - C++ / 백트래킹, 재귀 알고리즘 (0) | 2020.05.23 |
---|---|
[백준 15650] N과 M(2) - C++ / 백트래킹, 재귀 알고리즘 (0) | 2020.05.15 |
[백준 2583] 영역 구하기 - C++ / 알고리즘 DFS (0) | 2020.05.15 |
[백준 13549] 숨바꼭질 3 - C++ / 알고리즘 BFS, 우선순위 큐 (1) | 2020.04.25 |
[백준 13913] 숨바꼭질 4 - C++ / 알고리즘 BFS (0) | 2020.04.25 |