c++

백준 c++ 15649 문제 풀이

psb08 2025. 5. 16. 17:20
728x90
반응형

문제 링크 : 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