독일 로또는 {1, 2, ..., 49}에서 수 6개를 고른다.
로또 번호를 선택하는데 사용되는 가장 유명한 전략은 49가지 수 중 k(k>6)개의 수를 골라 집합 S를 만든 다음 그 수만 가지고 번호를 선택하는 것이다.
예를 들어, k=8, S={1,2,3,5,8,13,21,34}인 경우 이 집합 S에서 수를 고를 수 있는 경우의 수는 총 28가지이다. ([1,2,3,5,8,13], [1,2,3,5,8,21], [1,2,3,5,8,34], [1,2,3,5,13,21], ..., [3,5,8,13,21,34])
집합 S와 k가 주어졌을 때, 수를 고르는 모든 방법을 구하는 프로그램을 작성하시오.
입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있다. 첫 번째 수는 k (6 < k < 13)이고, 다음 k개 수는 집합 S에 포함되는 수이다. S의 원소는 오름차순으로 주어진다.
입력의 마지막 줄에는 0이 하나 주어진다.
각 테스트 케이스마다 수를 고르는 모든 방법을 출력한다. 이때, 사전 순으로 출력한다.
각 테스트 케이스 사이에는 빈 줄을 하나 출력한다.
<입력>
7 1 2 3 4 5 6 7
8 1 2 3 5 8 13 21 34
0
<출력>
1 2 3 4 5 6
1 2 3 4 5 7
1 2 3 4 6 7
1 2 3 5 6 7
1 2 4 5 6 7
1 3 4 5 6 7
2 3 4 5 6 7
1 2 3 5 8 13
1 2 3 5 8 21
1 2 3 5 8 34
1 2 3 5 13 21
1 2 3 5 13 34
1 2 3 5 21 34
1 2 3 8 13 21
1 2 3 8 13 34
1 2 3 8 21 34
1 2 3 13 21 34
1 2 5 8 13 21
1 2 5 8 13 34
1 2 5 8 21 34
1 2 5 13 21 34
1 2 8 13 21 34
1 3 5 8 13 21
1 3 5 8 13 34
1 3 5 8 21 34
1 3 5 13 21 34
1 3 8 13 21 34
1 5 8 13 21 34
2 3 5 8 13 21
2 3 5 8 13 34
2 3 5 8 21 34
2 3 5 13 21 34
2 3 8 13 21 34
2 5 8 13 21 34
3 5 8 13 21 34
아이디어
- 조합 문제 → dfs 알고리즘
import sys
sys.setrecursionlimit(10**6)
path = []
used = [0] * 50
def dfs(level):
global n
if level == 6:
answer = " ".join(str(i) for i in path)
print(answer)
return
for i in range(len(arr)):
if used[i] == 1:
continue
if len(path) > 0 and path[level-1] > arr[i]:
continue
used[i] = 1
path.append(arr[i])
dfs(level+1)
used[i] = 0
path.pop()
while 1:
arr = list(map(int, sys.stdin.readline().split()))
n = arr[0]
arr = arr[1:]
if n == 0:
break
dfs(0)
print()
처음에 제출했을 때 오답으로 떠서 어디에 문제가 있는지 곰곰히 생각해보았다. 알고보니 dfs 함수 for문에서 배열 안에 있는 값을 돌렸어야 됐는데 인덱스 값으로 돌리고 있었다.
중요한건 그렇게 했을 때 첫번째 테스트케이스가 정답으로 나온다는 것...ㅋㅋ 일부로 그렇게 만든듯ㅠㅠ
다른 분들의 코드를 보니 itertools 라이브러리의 combinations을 써서 더 간결하게 구현하신 분도 있었다.
나도 조합이나 순열 문제가 나오면 itertools를 써봐야겠다.
- itertools 라이브러리 combinations