[백준 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
댓글을 사용할 수 없습니다.