문제
https://www.acmicpc.net/problem/1759
문제 요약
알파벳 소문자로 이루어진 C개의 문자들이 주어졌을 때, 문자들을 조합하여 길이 L의 암호를 만들 수 있다.
만들 수 있는 모든 암호 경우의 수를 출력한다.
< 암호 규칙 >
1. 중복된 문자는 있을 수 없다.
2. 최소 1개의 모음(a, e, i, o u)으로 구성되어있다.
3. 최소 2개의 자음으로 구성되어있다.
4. 오름차순으로 정렬되어있다.
코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// C개 문자들로 만들어진 L자리 암호(문자열) 탐색
int L, C;
vector<char> chars;
vector<char> st;
// 현재 st가 조건에 부합하는지 확인
bool check() {
int vowel = 0;
// 현재 st의 모음 개수 판별
for (int i = 0; i < L; i++)
{
if (st[i] == 'a' || st[i] == 'e' || st[i] == 'i' || st[i] == 'o' || st[i] == 'u') {
vowel++;
}
}
// 모음 수 1개 이상 && 자음 수 (= 전체 - 모음 개수) 2개 이상.
if (vowel >= 1 && L - vowel >= 2) return true;
return false;
}
// num번째 문자에 대해 백트래킹 탐색
void dfs(int num) {
if (st.size() == L) { // 현재 st의 크기가 L 이고,
if (check()) { // 조건에 부합한다면
for (int i = 0; i < L; i++) {
cout << st[i];
}
cout << "\n";
}
return;
}
// 그 다음 가능한 문자에 대해 탐색
for (int i = num; i < C; i++) {
st.push_back(chars[i]);
dfs(i + 1);
st.pop_back();
}
return;
}
int main() {
// 입력
cin >> L >> C;
for (int i = 0; i < C; i++) {
char ch;
cin >> ch;
chars.push_back(ch);
}
// 오름차순 정렬
sort(chars.begin(), chars.end());
// 첫번째 문자부터 백트래킹 탐색
dfs(0);
return 0;
}
코드 설명
1. 입력 받은 C개의 문자들을 chars 벡터에 저장하고, 오름차순으로 탐색을 하기 위해 정렬한다.
2. vector에 저장된 0번째 문자부터 하나씩 st 벡터에 저장하며 탐색을 시작한다.
+ st 벡터는 스택 역할을 한다.
3. st의 크기가 L이 되고, 암호 조건에 부합하다면 st 내 요소를 모두 출력하고 종료한다.
+ 탐색이 종료되었다면, 스택에서 요소를 제거하고, 루프를 통해 다음 요소에 대한 탐색을 진행한다.
고찰
st에서 언제 요소를 넣고, 제거해야 하는지 헷갈렸다.
순서
1. i번째 문자를 st에 넣는다.
2. i + 1번째 문자에 대해 탐색한다.
3. 탐색이 종료되면 i번째 문자를 스택에서 제거한다.
=> 루프에 의해 가능한 다음 문자에 대해 진행한다.
'Algorithm Problems > 완전 탐색' 카테고리의 다른 글
[백준/C++] 2529번: 부등호 (0) | 2024.07.03 |
---|---|
[백준/C++] 14889번: 스타트와 링크 (0) | 2024.07.02 |
[백준/C++] 1535번: 안녕 (1) | 2024.04.10 |
[백준/C++] 18428번: 감시 피하기 (0) | 2024.03.17 |
[백준/C++] 28421번: 곱하기와 쿼리 (2) | 2024.02.23 |