문제 링크
접근
N개의 자연수 중, M개의 수를 뽑아 비내림차 수열을 만드는 문제이다.
이때 N개의 자연수는 (4, 4, 2)와 같이 중복된 숫자가 들어갈 수 있다.
예제 입력
4 2
9 7 9 1
예제 출력
1 7
1 9
7 9
9 9
위의 예제와 같이 (1, 7)이 뽑히면 추후 (7, 1)은 뽑을 수 없다.
따라서 N과 M(9)번 문제의 풀이에서 조건을 추가하여 문제를 풀었다.
조건 추가
(1, 7), (7, 1)과 같은 중복을 막기 위해 뽑을 수열을 (k-1번째 수, k번째 수)이라고 가정했을 때, k-1번째 수 > k번째 수이면 백트래킹을 하지 않고 패스한다.
코드
#include <iostream>
#include <algorithm>
#include <unordered_set>
using namespace std;
// N개 중에서, M개 뽑음
int N, M;
// n번째로 뽑은 수를 저장
int picked[10];
// 숫자 모음
int numbers[10];
// k번째 수를 중복으로 뽑았는지 확인
bool isUsed[10];
// k 번째로 저장할 수를 탐색
void Solve(int k)
{
if (k == M)
{
for (int i = 0; i < M; i++)
cout << picked[i] << ' ';
cout << '\n';
return;
}
// 현재 depth에서 마지막으로 뽑은 숫자 저장
int tmp = 0;
for (int i = 0; i < N; i++)
{
// 1. 같은 인덱스인 수를 중복해서 뽑았거나,
// 2. 같은 수가 여러개 있을 경우 생기는 중복 수열을 피한다.
// 3. (1, 7) (7, 1)과 같은 중복을 막기 위해
// (k - 1번째, k 번째)일 경우, k - 1번째 수 > k번째수이면
// 패스한다.
if (isUsed[i] || tmp == numbers[i] || (k > 0 && picked[k - 1] > numbers[i])) continue;
isUsed[i] = 1;
picked[k] = numbers[i];
tmp = picked[k];
Solve(k + 1);
isUsed[i] = 0;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> N >> M;
for (int i = 0; i < N; i++)
{
cin >> numbers[i];
}
// 사전순으로 찾기 위해 배열을 정렬
sort(numbers, numbers + N);
Solve(0);
return 0;
}
'알고리즘' 카테고리의 다른 글
[C++] Boj 15666 N과 M (12) (0) | 2025.02.06 |
---|---|
[C++] Boj 15665 N과 M (11) (0) | 2025.02.05 |
[C++] Boj 15663 N과 M (9) (0) | 2025.02.03 |
[C++] Boj 15657 N과 M (8) (0) | 2025.01.24 |
[C++] Boj 15656 N 과 M (7) (0) | 2025.01.23 |