중복 조합(Combination with Repetition)
N과 M이 주어졌을 때,
예:
N=4, M=2라면
1 1
1 2
1 3
1 4
2 2
2 3
2 4
3 3
3 4
4 4
이런 식의 "중복 조합" 형태가 나온다.
✔ 왜 start 파라미터가 필요할까?
중복은 허용하지만
비내림차순(이전 값보다 작으면 안 됨) 을 유지해야 한다.
즉,
for (int i = start; i <= N; i++) 로 시작start 가 핵심이다.
예시: N=3, M=2
dfs(0,1)
└ i=1 → arr[0]=1
→ dfs(1,1)
└ i=1 → arr[1]=1 → dfs(2,1) → 출력: 1 1
└ i=2 → arr[1]=2 → 출력: 1 2
└ i=3 → arr[1]=3 → 출력: 1 3
└ i=4 → arr[1]=4 → 출력: 1 4
└ i=2 …
중복 조합의 개수는

N,M ≤ 8 이므로 최대 약 6435개 정도.
배열 8개 채우는 수준 → O(M)
6천 × 8
= 약 5만 연산
➡ Java에서는 0.001초 수준
➡ 시간초과 걱정 전혀 없음
package algo.ct.M11;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BOJ_15652_N과M4_S3 {
static int[] arr;
static int N, M;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
arr = new int[M];
dfs(0, 1);
}
public static void dfs(int depth, int start) {
if (depth == M) {
for (int i = 0; i < M; i++)
System.out.print(arr[i] + " ");
System.out.println();
return;
}
for (int i = start; i <= N; i++) {
arr[depth] = i;
dfs(depth + 1, i);
}
}
}