diff --git "a/C++/[\353\260\261\354\244\200] \354\272\240\355\224\204\355\214\214\354\235\264\354\226\264 -3018.md" "b/C++/[\353\260\261\354\244\200] \354\272\240\355\224\204\355\214\214\354\235\264\354\226\264 -3018.md" new file mode 100644 index 0000000..5d70dac --- /dev/null +++ "b/C++/[\353\260\261\354\244\200] \354\272\240\355\224\204\355\214\214\354\235\264\354\226\264 -3018.md" @@ -0,0 +1,97 @@ +## 문제 +**문제** +이번 여름에 선영이와 친구들은 코딩 연습을 하기 위해 E일간 근처 바닷가로 MT를 갔다. + +매일 밤에는 캠프파이어 시간이 있다. 캠프파이어에 참가하는 사람들은 모두 모여서 노래를 부른다. 캠프파이어는 필수 코스가 아니기 때문에, 매일 참가하고 싶은 사람만 참가한다. + +MT에 참가한 사람 중 가장 인기있는 사람은 선영이다. + +매일 밤, 선영이가 캠프파이어에 참가한다면, 나머지 사람들이 모르는 새로운 노래를 즉석에서 만들어 부른다. 사람들은 모두 그 노래만 캠프파이어가 끝날 때까지 부른다. + +선영이가 피곤해서 캠프파이어에 참가하지 않는 날도 있다. 이 날은 사람들이 각자 아는 노래를 서로 공유한다. + +매일 캠프파이어에 참가하는 사람이 누구인지 주어졌을 때, 모든 노래를 알게되는 사람이 누구인지 구하는 프로그램을 작성하시오. + +**입력** +첫째 줄에 MT에 참가한 사람의 수 N이 주어진다. (1 ≤ N ≤ 100) 사람들은 1부터 N까지 번호가 매겨져 있으며, 선영이의 번호는 1이다. + +둘째 줄에는 E가 주어진다. (1 ≤ E ≤ 50) + +다음 E개 줄에는 그날 캠프파이어에 참가한 사람의 수 K와 참가한 사람의 번호가 주어진다. (2 ≤ K ≤ N) + +선영이는 적어도 한 번 캠프파이어에 참가한다. + +**출력** +MT가 끝났을 때, 선영이를 포함해 모든 노래를 아는 사람의 번호를 오름차순으로 출력한다. + +```cpp +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + + +int main() { + int N, E = 0; + long long allSong = 0; + long long songBit = 1; + cin >> N; + cin >> E; + + vector hearedSong(N + 1); + + + for (int i = 0; i < E; i++) { + + int num; + cin >> num; + + vector people; + for (int j = 0; j < num; j++) { + int personId; + cin >> personId; + people.push_back(personId); + } + + bool seonyeong = find(people.begin(), people.end(), 1) != people.end(); + + // 선영이가 있을 때 + if (seonyeong) { + + allSong |= (allSong << 1 | 1); + + for (int j = 0; j < num; j++) + hearedSong[people[j]] |= songBit; + + songBit = songBit << 1; + + } + else { + long long song_union = 0; + for (int j = 0; j < people.size(); j++) + song_union |= hearedSong[people[j]]; + + for (int j = 0; j < people.size(); j++) + hearedSong[people[j]] = song_union; + } + } + + + + for (int i = 0; i < hearedSong.size(); i++) + if ((hearedSong[i] & allSong) == allSong) + cout << i << endl; + + + return 0; +} +``` + +## 풀이 +비트플래그를 이용하여, 노래가 하나 추가될 때마다 시프트연산자를 사용해 한 칸 씩 밀어 노래를 3번 불렀다면 0b0111이 되도록했다. +선영이가 없을 경우 비트 or 연산을 통해 MT에 참가한 모든 사람들의 노래를 합집합 연산으로 합친뒤 대입해주었다.