
순열라이브러리와 DP를 통해 이항계수를 구한 풀이법
from itertools import permutations
n, f = map(int, input().split())
tri = [[1] * 11 for _ in range(11)]
tri[2][1] = 2
cnt = 0
for i in range(3, 11):
for j in range(1, i):
cnt += 1
tri[i][j] = tri[i - 1][j - 1] + tri[i - 1][j]
b = tri[n - 1]
b = b[:n]
seq = list(range(1, n + 1))
for v in permutations(seq):
seq = list(v)
res = 0
for i in range(n):
res += seq[i] * b[i]
if res == f:
print(*seq)
break
DFS를 이용한 풀이
n, f = map(int, input().split())
def dfs(l, sum):
if l == n and sum == f:
print(*p)
exit()
for i in range(1, n + 1):
if not ch[i]:
ch[i] = 1
p[l] = i
dfs(l + 1, sum + (p[l] * b[l]))
ch[i] = 0
p = [0] * n
b = [1] * n
for i in range(1, n - 1):
b[i] = b[i - 1] * (n - i) // i
ch = [0] * (n + 1)
dfs(0,0)
가장 밑의 줄에 있는 수 F는 구해야 하는 수열에서 이항계수만큼 곱해야 구할 수 있다는 것을 알아채야 풀 수 있는 문제였다.
문제에서 주어진 예시를 보자. 구해야 하는 수열은 3 1 2 4 인데 F=16은 \(3 * 1 + 1 * 3 + 2 * 3 + 4 * 1 \)의 결과값으로 수열에 곱한 계수는 각각 \( {}_3 C_0 \\~\\ {}_3 C_1 \\~\\ {}_3 C_2 \\~\\ {}_3 C_3 \\~\\\)과 같다. 즉, N-1일 때의 이항계수와 같다.
따라서 n이 주어지면 n에 해당하는 이항계수 리스트를 만들어서 F와 같은 값이 나올 때까지 모든 수열의 경우의 수와 곱하는 게 핵심 로직이 되겠다.
앞으로 파스칼의 삼각형을 이용한 문제(두개를 더한 값 이용)가 나오면 이항계수로 풀 수 있는 지 생각해보자
'Algorithm > DFS, BFS, 백트래킹' 카테고리의 다른 글
| [Java] 백준 15683 - 감시 (0) | 2023.06.19 |
|---|---|
| [Java]백준 1260 - DFS와 BFS (0) | 2023.04.20 |
| 섹션 7. 휴가 (0) | 2022.10.19 |
| 섹션 6. 순열 구하기 (0) | 2022.10.17 |
| 이진트리 순회(DFS) (0) | 2022.10.08 |