[문제 설명]
1010번: 다리 놓기
입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트케이스에 대해 강의 서쪽과 동쪽에 있는 사이트의 개수 정수 N, M (0 < N ≤ M < 30)이 주어진다.
www.acmicpc.net
[풀이 과정]
M개 중에 N개 선택하여 조합하는 경우의 수를 구하는 문제다.
조합 경우의 수를 구하는 방법은 여러가진데 메모이제이션을 이용하면 가장 효율적으로 풀 수 있다.
* 메모이제이션을 이용한 조합 경우의 수 구하기
- 메모이제이션(memoization) 기법은 동적 프로그래밍의(dynamic programming)의 일종이다.
메모를 할 배열을 만들어 놓고 처음 계산한 값은 배열에 저장한다.
이후 같은 계산을 반복할 때 다시 계산하지 않고 배열에 저장된 값을 바로 꺼내 사용한다.
* 이항계수
조합은 이항계수라는 성질을 가지고 있다.
nCr 이라는 조합이 있을 때,
- n==r 또는 r==0 일 때, nCr = 1
- 그 외, nCr = n-1Cr-1 + n-1Cr
메모이제이션과 이항계수로 조합을 구하면 다음과 같다.
public static int combination(int n, int r, int[][] memo) {
if (n==r || r==0) {
return 1;
}
if (memo[n][r] > 0) {
return memo[n][r];
}
memo[n][r] = solution(n-1, r-1, memo) + solution(n-1, r, memo);
return memo[n][r];
}
느낀점:
조합으로 구할 수 있는 모든 원소들의 패턴을 나열하라고 하면 완전탐색이 맞다.
하지만 개수를 구하는 것이라면 동적프로그래밍으로 풀어야 효율성이 좋다.
[JAVA code]
package com.algorithm.baekjoon.silver4;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Test03 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
StringTokenizer st;
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int[][] memo = new int[m + 1][n + 1];
int answer = solution(m, n, memo);
System.out.println(answer);
}
}
public static int solution(int m, int n, int[][] memo) {
if (m == n || n == 0) {
return 1;
}
if (memo[m][n] > 0) {
return memo[m][n];
}
memo[m][n] = solution(m - 1, n - 1, memo) + solution(m - 1, n, memo);
return memo[m][n];
}
}
'코딩 테스트 > 백준' 카테고리의 다른 글
[백준][Gold1]11401-이항계수3-JAVA (0) | 2021.04.27 |
---|---|
[백준][Gold1] 구간 합 구하기 - JAVA (0) | 2021.04.13 |
[백준][Gold1] 책 페이지 - JAVA (0) | 2021.04.10 |
[백준][Gold1] 제곱ㄴㄴ수 - JAVA (0) | 2021.04.07 |
[백준][silver4][JAVA]터렛 (2) | 2021.03.28 |