Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions C++/[백준] 캠프파이어 -3018.md
Original file line number Diff line number Diff line change
@@ -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 <string>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <numeric>
#include <sstream>

using namespace std;


int main() {
int N, E = 0;
long long allSong = 0;
long long songBit = 1;
cin >> N;
cin >> E;

vector<long long> hearedSong(N + 1);


for (int i = 0; i < E; i++) {

int num;
cin >> num;

vector<int> 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에 참가한 모든 사람들의 노래를 합집합 연산으로 합친뒤 대입해주었다.