반응형
고등 확률과 통계에서 배우는 순열과 조합이다.
순열과 조합을 구현하는데에 있어 매번 구글링 하기 귀찮아 좋은 정보를 얻어 정리를 해보려고한다.
덕분에 좋은 정보를 얻었다.
순열 nPr
void printArray(int a[], int r) {
for (int i = 0;i < r;i++) {
printf("%d ", a[i]);
}
printf("\n");
}
void permutation(int pArr[], bool check[], int n, int r, int depth) {
if (depth == r) {
printArray(pArr, r);
return;
}
for (int i = 1; i <= n; i++) {
if (!check[i]) {
check[i] = true;
pArr[depth] = i;
permutation(pArr, check, n, r, depth + 1);
check[i] = false;
}
}
}
int main(void) {
int n, r;
cin >> n >> r;
int* pArr = new int[r];
bool* check = new bool[n + 1];
for (int i = 0;i < r;i++) {
pArr[i] = 0;
}
for (int i = 0;i < n + 1;i++) {
check[i] = false;
}
permutation(pArr, check, n, r, 0);
return 0;
}
- pArr[] : n 까지의 숫자의 경우를 저장할 배열
- check[] : 순열에서 중복의 여부를 확인하는 배열 ( 이 배열을 뺀다면 중복 순열이 된다. )
알고리즘 설명
- check 가 false 인지 확인 ( 이미 나온 숫자인가? )
- false 이면 true 로 할당
- pArr[] 에 i 할당 ( 1부터 저장하기 위해 i = 1 로 지정 )
- Permutation(...,depth + 1) 실행하여 중복되지 않는 수를 확인하고 배열에 삽입
- depth == r 이 된다면 pArr 에 있는 원소 모두 출력
- check 를 차례대로 false 로 할당하면서 함수 빠져나옴
- for 문 반복
조합 nCr
void combination(int pArr[], int n, int r, int depth, int next) {
if (depth == r) {
printArray(pArr, r);
return;
}
for (int i = next; i <= n; i++) {
pArr[depth] = i;
combination(pArr,n, r, depth + 1, i+1);// i+1 을 i로 바꿔주면 중복 허용
}
}
int main(void) {
int n, r;
cin >> n >> r;
int* pArr = new int[r];
for (int i = 0;i < r;i++) {
pArr[i] = 0;
}
combination(pArr, n, r, 0, 1);
return 0;
}
순열과 다른 점
- 조합은 순열과 달리 오름차순으로 정렬이 된다.
따라서, for 문의 i 값이 combination 이 실행될 수록 이 전 i 값보다 커야한다.
그리고, check[] 배열을 사용하지 않는 이유는 i 값을 늘려줌으로써 이전의 i 값이나 동일한 값이 들어가지 않기 때문이다.
그래서, i 의 값을 유지시킨다면 중복 조합이 된다.
재귀로된 순열과 조합을 설명해 보았다.
하지만, 재귀인만큼 큰 수로 접근하게 된다면 overflow 발생 가능성도 있고 무엇보다 느리다.
이와 관련된 문제를 풀었었는데 까먹었다. ㅎㅎ
반응형
'BOJ' 카테고리의 다른 글
[백준 1018번] 체스판 다시 칠하기 (0) | 2021.05.03 |
---|---|
[백준 11758번] CCW (0) | 2021.04.30 |
[백준 9012번] 괄호 (0) | 2021.04.25 |
[백준 10773번] 제로 (0) | 2021.04.22 |
[백준 1546번] 평균 (0) | 2021.04.22 |