[Python] 백준 15651 N과 M (3) (Backtracking)

선주·2022년 2월 27일
0

Python PS

목록 보기
50/65
post-thumbnail

📌 문제

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

1부터 N까지 자연수 중에서 M개를 고른 수열
같은 수를 여러 번 골라도 된다.

입력

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

출력

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

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

예제 입력 1

3 1

예제 출력 1

1
2
3

예제 입력 2

4 2

예제 출력 2

1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4
3 1
3 2
3 3
3 4
4 1
4 2
4 3
4 4

예제 입력 3

3 3

예제 출력 3

1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
2 1 1
2 1 2
2 1 3
2 2 1
2 2 2
2 2 3
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3

📌 풀이

💬 Code

import sys
input = sys.stdin.readline

def dfs(cnt):
    if cnt == m:
        print(' '.join(map(str, arr)))
        return
    for i in range(1, n + 1):
        arr[cnt] = i
        dfs(cnt + 1)

n, m = map(int, input().split())
arr = [0 for _ in range(m)]
dfs(0)

💡 Solution

  • arr: 고른 m개의 숫자가 차례로 담기는 리스트
  • dfs(cnt): 숫자를 cnt개 선택한 상태에서 arr[cnt]를 고르는 함수

dfs가 재귀함수이므로 종료조건을 걸어줘야 한다. 그게 cnt == m일 때인데, 숫자를 m개 모두 선택한 상태라면 더이상 숫자를 선택하면 안되기 때문에 여태 고른 숫자를 출력해주고 리턴한다.

cnt != m이라면 아직 숫자를 골라야 한다. 1부터 n까지의 숫자를 요번 칸에 한번씩 넣어주고 다음 칸 숫자를 고르는 dfs를 부른다.


배열 원소 출력하기 (join() vs for문)

위가 join()으로 출력한 것, 아래가 for문으로 출력한 것인데 시간이 거의 2배나 차이가 나서 추가로 포스팅해본다. join()은 코드가 깔끔해지기만 하는 효과만 있는 줄 알았는데..!😵

for문은 리스트의 아이템 개수만큼 print() 함수를 호출하는 반면, join()은 print() 함수가 단 한 번만 호출되는 게 시간 차이의 주 원인인 것 같다.

join

print(' '.join(map(str, arr)))

for문

for j in arr:
    print(j, end=' ')
print()

참고
https://pdoubled.tistory.com/10

profile
기록하는 개발자 👀

0개의 댓글