문제보기
import java.util.*;
import java.io.*;
public class Main{
static int[][] d; // m원을 idx번째 동전까지 사용해서 만드는 경우의 수
static int[] c; // 동전 배열
static int go(int idx, int m){
if( m == 0 ){ // 목표 금액에 도달! -> 종료
return 1;
}
// 목표 금액보다 오바되었거나 더이상 사용할 수 있는 동전이 없을 때
if( m < 0 || idx < 0 ){
return 0;
}
// 메모된 것이 있다면 꺼내 쓰자
if(d[m][idx] != -1 ){
return d[m][idx];
}
// 결과를 담을 변수
int res = 0;
// 여기가 핵심인데, 현재 만들어야하는 금액을 큰 동전 갯수를 최대한 써가면서
// 하나씩 줄여가며 재귀를 보내주는 것이다
// 이렇게 해야 중복되는걸 세지 않게 된다
for(int i = m/c[idx] ; i >= 0 ; i-- ){
res += go(idx-1, m-c[idx]*i);
}
// 메모이제이션
d[m][idx] = res;
return res;
}
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 ){
int n = Integer.parseInt(br.readLine());
c = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 0 ; i < n ; i++){
c[i] = Integer.parseInt(st.nextToken());
}
int m = Integer.parseInt(br.readLine());
d = new int[m+1][n];
for(int i = 0 ; i <= m ; i++ ){
Arrays.fill(d[i], -1); // -1로 초기화
}
// 가장 큰 동전부터 사용하면서 m을 만들 수 있는 경우를 찾아본다
System.out.println(go(n-1, m));
}
}
}
Comments