문제 링크 : https://www.acmicpc.net/problem/15649
목차
1. 설명
2. 내 코드
3. 문제 풀이 해석 내용
4. 실행 결과
설명
백준 실버 3 문제 입니다.
문제명 : N과 M (1)
내 코드
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
void dfs(int N, int M, int depth, vector<bool>& visited, vector<int>& result)
{
if (depth == M)
{
for (int num : result)
{
cout << num << ' ';
}
cout << '\n';
return;
}
for (int i = 1; i <= N; ++i)
{
if (!visited[i])
{
visited[i] = true;
result.push_back(i);
dfs(N, M, depth + 1, visited, result);
result.pop_back();
visited[i] = false;
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n, m, depth = 0;
cin >> n >> m;
vector<bool> visited(n + 1, false);
vector<int> result;
dfs(n, m, 0, visited, result);
}
문제 풀이 해석 내용
깊이 우선 탐색 (DFS) 함수 정의
void dfs(int N, int M, int depth, vector<bool>& visited, vector<int>& result)
{
// ... (함수 내용) ...
}
dfs 함수는 재귀적으로 호출되어 순열을 생성하고 출력하는 핵심 함수입니다.
N: 사용할 자연수의 최대값 (1부터 N까지).
M: 선택할 자연수의 개수.
depth: 현재까지 몇 개의 자연수를 선택했는지 나타내는 깊이.
visited: 각 자연수(1부터 N까지)가 현재 순열에 사용되었는지 여부를 기록하는 불리언 벡터입니다. 참조(&)로 전달되어 함수 호출 간에 상태가 유지됩니다.
result: 현재까지 선택된 자연수들로 구성된 부분 순열을 저장하는 정수 벡터입니다. 참조(&)로 전달되어 요소를 추가하거나 제거하며 순열을 만듭니다.
DFS 함수 내부 - 기저 조건 (순열 완성)
if (depth == M) // M개의 숫자를 모두 골랐으면
{
for (int num : result) // 완성된 순열 출력
{
cout << num << ' ';
}
cout << '\n'; // 줄바꿈
return; // 함수 종료
}
depth == M: 현재까지 선택한 자연수의 개수(depth)가 목표 개수(M)와 같으면, 하나의 순열이 완성된 것입니다.
for (int num : result): result 벡터에 저장된 완성된 순열의 각 숫자를 순회하며 출력합니다. 숫자 사이에 공백을 추가합니다.
cout << '\n';: 하나의 순열 출력이 끝나면 줄바꿈합니다.
return;: 현재 재귀 호출을 종료하고 이전 단계로 돌아갑니다.
DFS 함수 내부 - 재귀 호출 (다음 숫자 선택)
for (int i = 1; i <= N; ++i) // 1부터 N까지의 각 자연수에 대해 시도
{
if (!visited[i]) // 아직 사용되지 않은 숫자이면
{
visited[i] = true; // i를 사용했다고 표시
result.push_back(i); // 결과 벡터에 i 추가
dfs(N, M, depth + 1, visited, result); // 다음 숫자를 고르기 위해 재귀 호출
result.pop_back(); // i를 제거 (다른 순열을 위해)
visited[i] = false; // i 사용 표시 해제 (다른 순열을 위해)
}
}
for (int i = 1; i <= N; ++i): 1부터 N까지의 각 자연수 i를 현재 위치에 놓을 수 있는지 시도합니다.
if (!visited[i]): 현재 자연수 i가 아직 현재 순열에 사용되지 않았다면. visited 벡터를 통해 중복 사용을 방지합니다.
visited[i] = true;: i를 사용한다고 표시합니다.
result.push_back(i);: 현재 선택된 자연수 i를 result 벡터의 끝에 추가합니다.
dfs(N, M, depth + 1, visited, result);: 다음 숫자를 고르기 위해 depth를 1 증가시켜 dfs 함수를 재귀적으로 호출합니다.
result.pop_back();: 재귀 호출이 끝난 후, 현재 순열에서 i를 제거합니다. 이는 다른 숫자를 같은 위치에 넣어 다른 순열을 만들기 위함입니다. (백트래킹)
visited[i] = false;: i의 사용 표시를 해제합니다. 역시 다른 순열을 만들 때 i를 다시 사용할 수 있도록 하기 위함입니다. (백트래킹)
메인 함수 내부 - 초기 설정 및 DFS 호출
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n, m, depth = 0; // N, M, 초기 깊이
cin >> n >> m;
vector<bool> visited(n + 1, false); // 방문 여부 벡터 (크기 N+1, 0번 인덱스는 사용 안함)
vector<int> result; // 결과 저장 벡터
dfs(n, m, 0, visited, result); // DFS 시작
입출력 최적화 설정은 위에서 설명했습니다.
int n, m, depth = 0;: 사용할 최대 자연수 n, 선택할 개수 m, 그리고 초기 깊이 0을 선언합니다.
cin >> n >> m;: 사용자로부터 n과 m 값을 입력받습니다.
vector<bool> visited(n + 1, false);: visited 벡터를 생성합니다. 크기는 n + 1로 하여 인덱스 1부터 n까지 사용 가능하게 하고, 모두 false로 초기화합니다.
vector<int> result;: 결과를 저장할 빈 벡터 result를 생성합니다.
dfs(n, m, 0, visited, result);: DFS 함수를 처음 호출하여 순열 생성을 시작합니다.
실행 결과

'c++' 카테고리의 다른 글
| 백준 c++ 1966 문제 풀이 (0) | 2025.05.18 |
|---|---|
| 백준 c++ 1269 문제 풀이 (0) | 2025.05.17 |
| 백준 c++ 7795 문제 풀이 (0) | 2025.05.15 |
| 백준 c++ 1920 문제 풀이 (0) | 2025.05.14 |
| 백준 c++ 1764 문제 풀이 (0) | 2025.05.13 |