백준 1759. 암호 만들기
알고리즘 기초 문제 중 브루트포스-재귀 문제(530)
1. 간단 설명
C개의 문자 중에서 L개를 뽑아 비밀번호를 만든다
생성한 비밀번호는 최소 한개의 모음과, 최소 두개의 자음으로 구성되어 있어야한다고 함
또한, 알파벳이 증가하는 순서로 배열되어있다고 한다
즉, abc는 가능하지만 bac처럼 순서가 거꾸로 되는건 안된다
2. 예시
abc -> 모음이 없어서 탈락
bac -> a가 b보다 빠르기 때문에 탈락
1
2
4 6
a t c i s w
atci -> 모음2개, 자음2개 OK atcs -> 모음2개, 자음2개 OK … tcsw -> 자음만 4개 탈락
이런식으로 비밀번호를 생성한 뒤 검증한다
3. 알고리즘
자음 모음을 분리해서 받아, 조합할때 하나씩 넣는 방법도 있겠지만
간단하게 하나의 벡터에 받은 다음에 나중에 검증하는식으로 구현했다
1
2
3
4
5
6
7
8
9
10
1. L과 C를 입력받는다
2. C개의 알파벳을 입력받는다
3. 입력받은 알파벳들을 정렬한다
4. 이 알파벳들로 조합을 생성해본다
4-1. 가지치기 조건 : 글자 수가 L개라면, 검증한다
4-1-1. 자음 2개, 모음1개라면 가능, 아니라면 불가능하므로 출력하지 않는다
4-2. 벡터의 알파벳이 사용되었는지 체크한다
4-2-1. 만약 사용되었다면 패스한다
4-2-2. 사용되지 않았다면, 이 알파벳을 넣는다
4-2-3. 재귀함수를 다시 호출한다
필요 변수들
int L, C
(3 ≤ L ≤ C ≤ 15)- 문자를 저장할 벡터
vector<char> ch
- 자음 모음 개수를 체크할 변수
int consonant, vowel
4. 소스코드
직접 구현한 조합 버전
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int L, C;
vector<char> v;
bool check(string str) {
int consonant = 0;
int vowel = 0;
for (char ch : str) {
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
vowel++;
else
consonant++;
}
if (consonant >= 2 && vowel >= 1) {
return true;
}
else {
return false;
}
}
void recursion(string str, int level, int start) {
if (str.size() == L) {
if (check(str)) {
cout << str << '\n';
}
return;
}
for (int i = start; i < v.size(); i++) {
str += v[i];
recursion(str, level + 1, i+1); // 현재 알파벳 다음 알파벳부터 보므로, 중복체크 필요없음
str.pop_back();
}
}
int main() {
// freopen_s(new FILE*, "input.txt", "r", stdin);
cin >> L >> C;
v.resize(C);
for (int i = 0; i < C; i++) {
cin >> v[i];
}
sort(v.begin(), v.end());
recursion("", 0, 0);
return 0;
}
- next_permutation을 이용한 조합
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <bits/stdc++.h>
using namespace std;
bool check(string str) {
int consonant = 0;
int vowel = 0;
for (char ch : str) {
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
vowel++;
else
consonant++;
}
if (consonant >= 2 && vowel >= 1) {
return true;
}
else {
return false;
}
}
int main() {
// freopen_s(new FILE*, "input.txt", "r", stdin);
int L, C;
vector<char> v;
cin >> L >> C;
v.resize(C);
for (int i = 0; i < C; i++) {
cin >> v[i];
}
sort(v.begin(), v.end());
vector<int> idx; // 조합을 위한 벡터
for (int i = 0; i < L; i++) {
idx.push_back(0);
}
for (int i = 0; i < C-L; i++) {
idx.push_back(1);
}
do {
string str = "";
for (int i = 0; i < idx.size(); i++) {
if (idx[i] == 0) {
str += v[i];
}
}
if (check(str)) {
cout << str << '\n';
}
} while (next_permutation(idx.begin(), idx.end()));
return 0;
}
2년전에 알고리즘 공부하다가 나중으로 미뤘던 문제였는데
오랜만에 다시 풀어보니 쉽게 풀렸다
역시 알고리즘은 꾸준히 공부하는게 답인듯 싶다
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.