1. 문제설명
도시에는 도시를 동쪽과 서쪽으로 나누는 큰 일직선 모양의 강의 흐르고 있다. 다리를 짓기로 하고, 짓기에 적합한 곳(사이트)이 서쪽에 N개, 동쪽에는 M개가 있다.(N≤M) 한 사이트에는 최대 한 개의 다리만 연결될 수 있고, 다리를 최대한 많이 짓기 위해 서쪽의 사이트 개수만큼(N개) 다리를 지으려고 한다.
다리끼리는 서로 겹쳐질 수 없다고 할 때 다리를 지을 수 있는 경우의 수를 구하는 문제이다.
- 시간 제한: 0.5초
- 메모리 제한: 128MB
2. 접근 방식
- 조합의 개념을 사용한다.
- nCr : 서로 다른 n개의 원소에서 r(단, 0<r≤n)개를 중복없이, 순서를 고려하지 않고 선택하는 것
- nCr=n−1Cr−1+n−1Cr
int dp[][]
배열을 사용하여 조합의 값을 저장한다.- DP의 Top-Down 방식을 사용한다.
- n−1Cr−1과 n−1Cr을 재귀 호출을 통해 nCr의 값을 저장한다.
- n이 r과 같거나, r이 1이면, 해당 배열에 1을 저장하고 반환한다.
- 마지막으로 nCr의 값을 반환한다.
3. 최종 코드
import java.io.*;
import java.util.*;
public class Main {
static int n, m;
static int[][] dp; // 조합의 값을 저장할 배열
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
while(t-- > 0) {
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
dp = new int[m+1][m+1]; // dp 배열 초기화
// m개 중에서 n개를 선택하는 조합의 경우의 수를 구함
System.out.println(combination(m, n));
}
}
static int combination(int n, int r) {
// 이미 계산을 한 경우, 그 값을 반환
if(dp[n][r] > 0) return dp[n][r];
// nCn 또는 nC1이면 값은 1로 반환
if(n==r || r==0) return dp[n][r] = 1;
// 재귀 호출을 통해 점화식을 만족하는 조합의 값을 계산
dp[n][r] = combination(n-1, r-1) + combination(n-1, r);
return dp[n][r]; // nCr 값을 반환
}
}
4. 느낀점 or 기억할정보
문제를 보고 조합 개념을 사용하면 된다는 것은 바로 파악했지만, 점화식은 찾아보게 되었다.
반응형
'알고리즘 문제 > 백준' 카테고리의 다른 글
[백준] 9655번: 돌 게임 (Java) (0) | 2024.08.27 |
---|---|
[백준] 9095번: 1,2,3 더하기 (Java) (0) | 2024.08.26 |
[백준] 2748번: 피보나치 수 2 (Java) (0) | 2024.08.26 |
[백준] 1743번: 음식물 피하기 (Java) (0) | 2024.08.25 |
[백준] 1991번: 트리 순회 (Java) (0) | 2024.08.25 |
댓글