[백준 / Swift] 15649 - N과 M (1)

박준혁 - Niro·2023년 1월 20일
0

백준

목록 보기
11/16
post-thumbnail

🔗 문제 링크


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


💡 문제


자연수 N과 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.

  • 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열

⌨️ 입력


첫째 줄에 자연수 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)


🖨️ 출력


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

수열은 사전 순으로 증가하는 순서로 출력해야 한다.


✅ 풀이


조건을 만족하는 길이가 M인 수열을 모두 구하는 문제입니다.
모든 수열을 구한다는 것은 말 그대로 모든 경우의 수 를 전부 체크를 해야합니다.

하지만 이 문제에서는 1부터 N까지 자연수 중에 중복이 없이 M개를 골라야 하는 조건 이 있으므로 완전탐색인 브루트포스 알고리즘이 아닌 백트래킹 알고리즘 을 통해 문제를 해결해야 합니다.

순서

  1. 입력받은 수를 n과 m에 저장

  2. 해당 노드를 방문했는지 확인을 위한 Bool형 배열 (visited) 선언

  3. 결과값을 출력하기 위한 String 변수 result 선언 (배열보다 시간 단축)

  4. 백트래킹 알고리즘은 재귀함수를 이용하기 때문에 dfs 함수를 선언

  5. 결과값을 저장할 temp와 노드의 깊이를 알려줄 depth 매개변수 선언

  6. depth 와 m 이 같다는 것은 한줄에 출력할 수를 골랐기 때문에 result에 저장
    다른 자식 노드를 가야하기 때문에 return 으로 함수 종료

  7. visited의 각 인덱스 마다 방문하지 않았다면 (false) 방문한것으로 바꾸기 (true)

  8. 다음 자식 노드로 탐색해야하기 때문에 dfs 함수를 다시 불러오기 (재귀)

  9. n번만큼 반복문이 돌았다면 부모 노드로 돌아가고 방문했던 노드는 false로 바꾸기

🖥️ 소스 코드


let input = readLine()!.split(separator: " ").map{Int(String($0))!}

let n = input[0]
let m = input[1]
var visited = Array(repeating: false, count: n+1)
var result = ""

func dfs (depth: Int, temp: String) {
    if depth == m {
        result += "\(temp)\n"
        return
    }
    
    for i in 1...n {
        if !visited[i] {
            visited[i] = true
            dfs(depth: depth + 1, temp: temp + "\(i) ")
            visited[i] = false
        }
    }
}

dfs(depth: 0, temp: "")
print(result)
profile
📱iOS Developer, 🍎 Apple Developer Academy @ POSTECH 1st, 💻 DO SOPT 33th iOS Part

0개의 댓글