반응형
1062번: 가르침
첫째 줄에 단어의 개수 N과 K가 주어진다. N은 50보다 작거나 같은 자연수이고, K는 26보다 작거나 같은 자연수 또는 0이다. 둘째 줄부터 N개의 줄에 남극 언어의 단어가 주어진다. 단어는 영어 소문
www.acmicpc.net
조합을 구현할 수 있는지 없는지에 대한 문제였다. 조합을 구현할 줄 알면 나름 수월하게 풀 수 있다. 하지만 나는 조합을 구현할 줄 몰랐기 때문에 조합을 구현하는 것부터 배웠다. '알고리즘' 파트에 조합, 중복조합, 순열, 중복순열에 대한 글을 정리해놨다. 클릭 바로가기!
문제를 읽고 이해하기까지 5분 정도 걸린 것 같다. 이 문제에서 주의할 점은 모든 단어가 'anta'로 시작하고 'tica'로 끝난다는 점이다. 따라서 a, n, t, i, c 다섯 글자가 K 안에 항상 포함된다. 즉, K가 5보다 작으면 정답은 항상 0을 출력, K가 26이면 모든 글자를 배운 경우이므로 N을 출력하면 된다.
원리는 간단하다. 조합을 구현하고 K 개의 문자를 선택한 모든 경우에 대해 check() 함수를 돌리면 된다. check() 함수는 선택한 알파벳으로 읽을 수 있는 단어의 개수를 반환해주는 함수다.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
// a n t i c
// 조합으로 선택하면서 k개 선택하면 check로 가능한 단어 개수 검사
char alpha[26];
int sel[26] = {0,};
string *str;
int Max = 0;
int check(int size){
// 모든 문자열 검색하면서 읽을 수 있는지 검색
int len, ans = 0;
for(int i = 0; i < size; i++){
len = 0;
for(int idx = 0; idx < str[i].length(); idx++){
if(sel[(int)(str[i][idx] - 'a')]) len++;
}
if(len == str[i].length()) ans++;
}
return ans;
}
// 조합 구현
void DFS(int idx, int cnt, int N, int k){
if(cnt == k){
Max = max(Max, check(N));
return;
}
for(int i = idx; i < 26; i++){
if(sel[i] == 1) continue;
sel[i] = 1;
DFS(i, cnt + 1, N, k);
sel[i] = 0;
}
}
int main(){
int N, K;
cin >> N >> K;
// 예외처리
if(K < 5){
cout << 0 << endl;
return 0;
}
if(K == 26){
cout << N << endl;
return 0;
}
str = new string[N];
string tmp;
for(int i = 0; i < N; i++){
cin >> tmp;
// 'anta'와 'tica'는 제외하고 저장해준다
str[i] = tmp.substr(4, tmp.length() - 8);
}
sel[(int)('a' - 'a')] = 1;
sel[(int)('n' - 'a')] = 1;
sel[(int)('t' - 'a')] = 1;
sel[(int)('i' - 'a')] = 1;
sel[(int)('c' - 'a')] = 1;
for(int i = 0; i < 26; i++)
alpha[i] = 'a' + 0;
DFS(0, 0, N, K - 5);
cout << Max << endl;
delete[] str;
return 0;
}
반응형
'알고리즘 문제풀이 > 추천 문제' 카테고리의 다른 글
[ 백준 2504 ] 괄호의 값 (C++) (0) | 2022.01.17 |
---|---|
[ 백준 1918 ] 후위 표기식 (C++) (0) | 2022.01.17 |
[ 백준 14719 ] 빗물 (C++) (0) | 2022.01.17 |
[ 백준 1935 ] 후위 표기식2 (C++) (0) | 2022.01.17 |
[ 백준 14888 ] 연산자 끼워넣기 (C++) (0) | 2022.01.17 |