다리 놓기 - 1010
성능 요약
메모리: 31256 KB, 시간: 88 ms
분류
조합론, 다이나믹 프로그래밍, 수학
문제 설명
재원이는 한 도시의 시장이 되었다. 이 도시에는 도시를 동쪽과 서쪽으로 나누는 큰 일직선 모양의 강이 흐르고 있다. 하지만 재원이는 다리가 없어서 시민들이 강을 건너는데 큰 불편을 겪고 있음을 알고 다리를 짓기로 결심하였다. 강 주변에서 다리를 짓기에 적합한 곳을 사이트라고 한다. 재원이는 강 주변을 면밀히 조사해 본 결과 강의 서쪽에는 N개의 사이트가 있고 동쪽에는 M개의 사이트가 있다는 것을 알았다. (N ≤ M)
재원이는 서쪽의 사이트와 동쪽의 사이트를 다리로 연결하려고 한다. (이때 한 사이트에는 최대 한 개의 다리만 연결될 수 있다.) 재원이는 다리를 최대한 많이 지으려고 하기 때문에 서쪽의 사이트 개수만큼 (N개) 다리를 지으려고 한다. 다리끼리는 서로 겹쳐질 수 없다고 할 때 다리를 지을 수 있는 경우의 수를 구하는 프로그램을 작성하라.
입력
입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트케이스에 대해 강의 서쪽과 동쪽에 있는 사이트의 개수 정수 N, M (0 < N ≤ M < 30)이 주어진다.
출력
각 테스트 케이스에 대해 주어진 조건하에 다리를 지을 수 있는 경우의 수를 출력한다.
문제 풀이
먼저 이 문제는 여러가지로 순열인 팩토리얼로 문제를 풀 수 있지만, 팩토리얼을 사용하는 것 보다, dp를 이용하는 것이 더 빠르다고 생각하여, 다이나믹 프로그래밍에서 Bottom-Up 방식으로 문제를 풀었습니다.
아래 글은 다이나믹 프로그래밍 Bottom-up에 대해 설명한 글입입니다.
참조
n m | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
2 | x | 1 | 3 | 6 | 10 | 15 | 21 |
3 | x | x | 1 | 4 | 10 | 20 | 35 |
4 | x | x | x | 1 | 5 | 15 | 35 |
5 | x | x | x | x | 1 | 6 | 21 |
표의 규칙성을 보면 (2,3) = (1,2) + (2+2)
점화식으로는 (i,j) = (i-1,j-1) + (i,j-1)
점화식를 바탕으로 DP bottom-up 을 사용하여 풀이
1. 초기화하기
dp = [[1]*(m+1) for _ in range(m+1)] # dp 리스트를 m만큼 생성한다. 그리고 모든 수를 1로 만든다.
모든 수를 1로 만드는 이유는 dp의 행렬 같다면 1이기 때문에 먼저 삽입하였습니다.
참조
2. n이 1 이라면 경우의 수는 m
for i in range(2,m+1):
dp[1][i]=i
3. 점화식을 활용한 dp배열 삽입
for i in range(2,n+1):
for j in range(i+1,m+1):
dp[i][j] = dp[i-1][j-1] + dp[i][j-1]
위 표의 규칙성을 이용한 점화식을 사용
전체 코드
def dp_b (n,m) :
dp = [[1]*(m+1) for _ in range(m+1)]
for i in range(2,m+1):
dp[1][i]=i
for i in range(2,n+1):
for j in range(i+1,m+1):
dp[i][j] = dp[i-1][j-1] + dp[i][j-1]
return dp[n][m]
for _ in range(int(input())):
west, east = map(int, input().split())
print(dp_b(west,east))
'코딩테스트 > 백준' 카테고리의 다른 글
[백준][1003] - 피보나치 함수 python 파이썬 (2) | 2023.04.19 |
---|---|
[백준][11866] - 요세푸스 문제 python 파이썬 (0) | 2023.04.19 |
[백준][10845][Silver 4] - 큐 python (0) | 2023.04.16 |
[백준][1427][Silver 5] - 소트인사이드 python (0) | 2023.04.14 |
[백준][2839][Silver 4] - 설탕배달 python (0) | 2023.04.13 |