Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
Tags
- #코드트리 #코딩테스트 #코테공부 #백트래킹 #알고리즘 기초
- 코딩테스트준비
- 데이터베이스
- 플로이드-워셜
- 인접 행렬
- 알고리즘
- 자바스크립트
- 오블완
- 파이썬
- 프로그래밍 언어
- 코딩테스트
- 1일1코테
- 코드트리
- 항해99
- 개발자루틴
- 코딩테스트사이트추천
- 자료구조
- 갭체크
- 티스토리챌린지
- til
- C
- 웹
- 프로그래머스
- 자바
- Java
- 코테공부
- 운영체제
- 99클럽
- 연결 리스트
- 개발자취업
Archives
- Today
- Total
와드의 블로그
1759번: 암호 만들기 본문
문제
서로 다른 L개의 알파벳 소문자들로 구성된 암호를 추측하는 문제입니다. 암호는 다음과 같은 조건을 만족해야 합니다.
- 최소 한 개의 모음(a, e, i, o, u)과 최소 두 개의 자음으로 구성되어 있습니다.
- 암호를 이루는 알파벳은 오름차순으로 배열되어 있습니다. (예: abc는 가능하지만 bac는 불가능)
C개의 문자가 주어졌을 때, 가능성 있는 모든 암호를 사전식으로 출력하는 프로그램을 작성해야 합니다.
- 입력: 첫째 줄에 두 정수 L, C가 주어집니다. (3 ≤ L ≤ C ≤ 15) 둘째 줄에는 C개의 문자들이 공백으로 구분되어 주어집니다.
- 출력: 각 줄에 하나씩, 사전식으로 가능성 있는 암호를 모두 출력합니다.
풀이: 정렬을 동반한 조합 탐색 및 유효성 검사
배열을 정렬하여 탐색 순서를 강제하고, 시작 인덱스를 매개변수로 전달하는 조합(Combination)의 정석적인 풀이입니다.
- 사전 정렬: 입력받은 C개의 문자를 Arrays.sort()를 통해 사전순으로 정렬합니다. 정렬된 배열을 순차적으로 탐색하면 완성된 암호들도 자연스럽게 사전식으로 도출됩니다.
- 백트래킹 전개 (go 함수):
- idx는 다음으로 선택할 문자의 인덱스를 의미하며, s는 현재까지 구성된 암호 문자열입니다.
- 반복문은 항상 전달받은 idx부터 시작하므로 이전에 선택한 문자보다 사전순으로 뒤에 있는 문자만 선택하게 되어 오름차순 조건이 유지됩니다.
- 유효성 검사 최적화 (check 함수):
- 완성된 길이 L의 문자열을 순회하며 모음(a, e, i, o, u)의 개수(cnt)를 카운트합니다.
- 별도의 자음 카운트 변수를 둘 필요 없이, 전체 길이에서 모음의 개수를 뺀 값(s.length() - cnt)이 곧 자음의 개수가 된다는 성질을 이용합니다.
- 모음이 1개 이상이고, 자음이 2개 이상일 때만 true를 반환하여 최종적으로 StringBuilder에 덧붙입니다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int l, c;
static char[] a;
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
l = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
a = new char[c];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < c; i++) {
a[i] = st.nextToken().charAt(0);
}
// 사전순으로 암호를 출력하기 위해 입력된 문자들을 미리 오름차순 정렬
Arrays.sort(a);
// 깊이 0, 빈 문자열로 탐색 시작
go(0, "");
bw.write(sb.toString());
bw.flush();
}
// idx: 탐색을 시작할 위치, s: 현재까지 만들어진 문자열
static void go(int idx, String s) {
// 암호의 길이인 l에 도달한 경우 (기저 조건)
if (s.length() == l) {
// 모음/자음 개수 조건을 만족하는지 확인
if (check(s)) {
sb.append(s).append("\n");
}
return;
}
// 현재 인덱스 idx부터 탐색하여 오름차순 유지 (조합)
for (int i = idx; i < c; i++) {
go(i + 1, s + a[i]);
}
}
// 완성된 문자열이 최소 1개의 모음과 최소 2개의 자음을 포함하는지 검사
static boolean check(String s) {
int cnt = 0; // 모음 개수
for (char c : s.toCharArray()) {
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
cnt++;
}
}
// 모음이 1개 이상이고, 전체 길이에서 모음을 뺀 자음의 개수가 2개 이상이어야 함
return cnt >= 1 && s.length() - cnt >= 2;
}
}
알고리즘 분류
수학 (Mathematics), 브루트포스 알고리즘 (Brute Force), 조합론 (Combinatorics), 백트래킹 (Backtracking)
'PS > B.O.J' 카테고리의 다른 글
| 15661번: 링크와 스타트 (0) | 2026.04.29 |
|---|---|
| 14501번: 퇴사 (0) | 2026.04.29 |
| 18290번: NM과 K (1) (0) | 2026.04.28 |
| 1748번: 수 이어 쓰기 1 (0) | 2026.04.28 |
| 14500번: 테트로미노 (0) | 2026.04.28 |