N개 중 M개를 뽑아 나열하는 경우의 수 시리즈이다.
기본적으로 백트래킹을 이용해서 재귀로 구현함.
9~12같은 경우 중복을 제거해줘야 하는데, 이건 set<vector<int>>로 해결하였다.
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
void printPicked(vector<int>& picked) {
for (int n : picked) printf("%d ", n + 1);
printf("\n");
}
int n, m;
void pick(vector<int>& picked, vector<bool>& isUsed, int k) {
if (k == m) {
printPicked(picked);
return;
}
for (int next = 0; next < n; next++) {
if (!isUsed[next]) {
picked[k] = next;
isUsed[next] = true;
pick(picked, isUsed, k + 1);
isUsed[next] = false;
}
}
}
int main() {
scanf("%d %d", &n, &m);
vector<int> picked(m, 0);
vector<bool> isUsed(n, false);
pick(picked, isUsed, 0);
}
재귀에 고른 수들 혹은 고른 수들의 인덱스를 저장할 picked 벡터와 여태 고른 수의 개수 k를 전달하는 것이 핵심이다.
오름차순의 경우 isUsed가 필요없다.
N과 M(9~12)는 다음과 같이 짜 보았다.
#include <vector>
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
int arr[8], n, m;
set<vector<int>> rst;
void pick(vector<int>& picked, vector<bool>& isUsed, int k) {
if (k == m) {
rst.insert(picked);
return;
}
for (int i = 0; i < n; i++) {
if (!isUsed[i]) {
isUsed[i] = true;
picked.push_back(arr[i]);
pick(picked, isUsed, k + 1);
isUsed[i] = false;
picked.pop_back();
}
}
}
int main() {
scanf("%d %d", &n, &m);
vector<int> picked;
vector<bool> isUsed(n,false);
for (int i = 0; i < n; i++) scanf("%d", &arr[i]);
sort(arr, arr + n);
pick(picked, isUsed, 0);
for (auto s : rst) {
for (auto num : s) printf("%d ", num);
printf("\n");
}
}
'알고리즘 > 백준 & swacademy' 카테고리의 다른 글
BOJ 1182 - 부분수열의 합 (0) | 2019.07.06 |
---|---|
BOJ 9663 - N QUEEN (0) | 2019.07.06 |
BOJ 2448 - 별찍기11 (0) | 2019.07.04 |
BOJ 1074 - Z (0) | 2019.07.04 |
(인강)기초-dp1 (0) | 2019.06.23 |