[백준 1062번 C/C++] 가르침
[백준 1062번 C/C++] 가르침
https://www.acmicpc.net/problem/1062
해결전략
비트마스킹 Bitmasking
백트래킹
정답 코드
#include <algorithm>
#include <iostream>
#include <bitset>
#include <vector>
#include <set>
using namespace std;
int n, k; // n: 단어의 수, k: 배울 수 있는 알파벳의 수
int answer; // 최대 읽을 수 있는 단어의 수를 저장하는 변수
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> k;
vector<string> words(n); // 단어들을 저장할 벡터
for (int i = 0; i < n; i++) {
cin >> words[i];
}
// k가 5보다 작은 경우는 읽을 수 있는 단어가 없으므로 0을 출력
if (k < 5) {
cout << "0\n";
return 0;
}
// 필수로 배워야 하는 알파벳 설정 (a, n, t, i, c)
bitset<26> alphabet;
alphabet['a'-'a'] = alphabet['n'-'a'] = alphabet['t'-'a'] = alphabet['i'-'a'] = alphabet['c'-'a'] = true;
set<char> allCandidates; // 추가로 배울 수 있는 알파벳 후보를 저장하는 집합
for (int i = 0; i < n; i++)
{
for (int j = 4; j < words[i].size() - 4; j++) // 각 단어의 문자 분석
{
if (false == alphabet[ words[i][j] - 'a' ]) { // 필수 알파벳이 아닌 경우에만 후보에 추가
allCandidates.insert(words[i][j]);
}
}
}
vector<char> can(allCandidates.begin(), allCandidates.end()); // 후보 알파벳을 벡터로 변환
int canSize = can.size(); // 후보 알파벳의 수
// 조합을 이용한 가능한 모든 경우의 수를 확인하기 위한 벡터 초기화
vector<bool> comb(canSize, false);
fill(comb.begin() + canSize - min(canSize, k - 5), comb.end(), true); // k - 5를 고려하여 초기화
do {
bitset<26> learned = alphabet; // 현재 조합에서 배운 알파벳을 저장하는 비트셋
for (int i = 0; i < canSize; i++)
{
// 현재 조합에서 선택된 알파벳을 learned 비트셋에 추가
if (comb[i]) {
learned[can[i] - 'a'] = true;
}
}
int cnt = 0; // 현재 조합으로 읽을 수 있는 단어의 수
for (int i = 0; i < n; i++)
{
bool canRead = true; // 현재 단어를 읽을 수 있는지 여부
for (int j = 0; j < words[i].size(); j++)
{
// 현재 단어의 모든 문자가 learned 비트셋에 있는지 확인
if (false == learned[ words[i][j] - 'a' ]) {
canRead = false;
break;
}
}
// 단어를 읽을 수 있는 경우 카운트 증가
if (canRead) {
cnt++;
}
}
answer = max(answer, cnt); // 최대 읽을 수 있는 단어의 수를 업데이트
} while (next_permutation(comb.begin(), comb.end()));
cout << answer << "\n";
return 0;
}
정답코드2
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int n, k;
int answer;
vector<int> words;
// DFS를 사용하여 알파벳의 조합을 찾는 함수
void DFS(int len, int alpha, int hash)
{
if (len == k) // 알파벳 k개 선택 완료
{
int result = 0;
// 현재 hash값으로 읽을 수 있는 word 개수 카운팅
for (int i = 0; i < n; i++)
{
if ((hash & words[i]) == words[i]) { // 현재 선택된 알파벳이 단어에 포함되어 있는지 확인
result++;
}
}
answer = max(answer, result);
return;
}
// 26개 알파벳 중 아직 선택되지 않은 알파벳을 선택. 26개 알파벳 중 k - 5개 알파벳 선택.
for (int i = alpha; i < 26; i++)
{
if (hash & (1 << i)) continue; // 이미 선택된 알파벳은 건너뛰기
DFS(len + 1, i + 1, hash | (1 << i)); // 다음 알파벳 선택
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> k;
words.resize(n);
string input;
for (int i = 0; i < n; ++i) {
cin >> input;
for (int j = 0; j < input.size(); ++j) { // 입력 단어에 대한 hash값 계산 후 저장.
words[i] |= (1 << (input[j] - 'a'));
}
}
int hash = 0;
string essentialAlphabet = "acint";
for (int i = 0; i < essentialAlphabet.size(); i++)
{
hash |= (1 << (essentialAlphabet[i] - 'a')); // 필수 알파벳 'a', 'c', 'i', 'n', 't'를 hash에 추가.
}
if (k < 5) { // k가 5보다 작은 경우는 필수 알파벳만으로는 단어를 읽을 수 없으므로 0 출력
cout << "0";
}
else if (k >= 26){ // k가 26인 경우는 모든 알파벳을 배울 수 있으므로 모든 단어를 읽을 수 있음
cout << n;
}
else
{
DFS(5, 0, hash); // 5는 필수 알파벳을 이미 선택했으므로 DFS를 5에서 시작
cout << answer;
}
return 0;
}
'⭐ 코딩테스트 > 백준' 카테고리의 다른 글
[백준 2573번 C/C++] 빙산 (0) | 2024.08.26 |
---|---|
[백준 20055번 C/C++] 컨베이어 벨트 위의 로봇 (0) | 2024.08.23 |
[백준 2098번 C/C++] 외판원 순회 (0) | 2024.08.08 |
[백준 14391번 C/C++] 종이 조각 (0) | 2024.08.07 |
[백준 15661번 C++] 링크와 스타트 (0) | 2024.08.06 |
댓글
이 글 공유하기
다른 글
-
[백준 2573번 C/C++] 빙산
[백준 2573번 C/C++] 빙산
2024.08.26 -
[백준 20055번 C/C++] 컨베이어 벨트 위의 로봇
[백준 20055번 C/C++] 컨베이어 벨트 위의 로봇
2024.08.23 -
[백준 2098번 C/C++] 외판원 순회
[백준 2098번 C/C++] 외판원 순회
2024.08.08 -
[백준 14391번 C/C++] 종이 조각
[백준 14391번 C/C++] 종이 조각
2024.08.07