https://www.acmicpc.net/problem/15652
N과 M (4)
문제
자연수 N과 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.
- 1부터 N까지 자연수 중에서 M개를 고른 수열
- 같은 수를 여러 번 골라도 된다.
- 고른 수열은 비내림차순이어야 한다.
- 길이가 K인 수열 A가 A1 ≤ A2 ≤ ... ≤ AK-1 ≤ AK를 만족하면, 비내림차순이라고 한다.
입력
첫째 줄에 자연수 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)
출력
한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다.
수열은 사전 순으로 증가하는 순서로 출력해야 한다.
예제 입력 1 복사
3 1
예제 출력 1 복사
1
2
3
예제 입력 2 복사
4 2
예제 출력 2 복사
1 1
1 2
1 3
1 4
2 2
2 3
2 4
3 3
3 4
4 4
예제 입력 3 복사
3 3
예제 출력 3 복사
1 1 1
1 1 2
1 1 3
1 2 2
1 2 3
1 3 3
2 2 2
2 2 3
2 3 3
3 3 3
풀이
import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Main {
static int N,M;
static int[] num;
static ArrayList<Integer> sequence = new ArrayList<>();
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
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());
num = new int[N+1]; // 1부터 시작
for (int i=1; i<N+1; i++){
num[i] = i;
}
DFS(1,0);
bw.flush();
bw.close();
}
private static void DFS(int start, int depth)throws IOException{
if (depth == M){
for (int seq : sequence){
bw.write(seq + " ");
}
bw.write("\n");
return;
}
for (int i=start; i<N+1; i++){
sequence.add(num[i]);
DFS(i, depth+1);
sequence.remove(sequence.size()-1); // 백트래킹
}
}
}
- DFS, 백트래킹을 활용한 문제
- 1 ~ N까지의 자연수 중 M개를 고른 수열을 고르되, 아래 조건을 만족해야한다.
- 같은수를 여러번 골라도 된다.
- 오름차순 정렬
- 중복되는 수열을 여러번 출력해선 안된다.
- 여기서 관건은, 같은 수를 여러번 골라도 되나, 중복되는 수열을 출력하면 안된다.
- 따라서 start값을 받아서 num배열에서 몇 번째 index 부터 쓸 것인지 정하면된다.
for (int i=start; i<N+1; i++){
sequence.add(num[i]);
DFS(i, depth+1);
sequence.remove(sequence.size()-1); // 백트래킹
}
- DFS 재귀호출 부분에서 for문을 그냥 i=1 ~ N까지 순회하게 되면 중복된 수열을 출력하게 된다.
- 예를 들어서 1 2와 2 1 은 같은 수열로 취급해버리기 때문이다.
- 따라서 어차피 오름차순 정렬이기 때문에 현재 i값을 가지고 재귀호출 파라미터에 start값을 i로 주면 중복수열을 방지할 수 있다.
해당문제는 백준 15650 N과 M(2) 문제와 유사하다
'코딩테스트 > 백준' 카테고리의 다른 글
[백준 6603] 로또 (Java) - DFS, 백트래킹 (0) | 2025.05.01 |
---|---|
[백준 26169] 세 번 이내에 사과를 먹자 (Java) - DFS, 백트래킹 (1) | 2025.04.30 |
[백준 15651] N과 M(3) (Java) - DFS, 백트래킹 (0) | 2025.04.28 |
[백준 10974] 모든 순열 (Java) - DFS, 백트래킹 (0) | 2025.04.28 |
[백준 14888] 연산자 끼워넣기 (Java) - 브루트포스, DFS, 백트래킹 (0) | 2025.04.27 |