https://www.acmicpc.net/problem/1497
문제
강토는 Day Of Mourning의 기타리스트로, 다가오는 공연을 준비하고 있다.
어느 날 강토의 집에 도둑이 들어서 기타를 모두 도둑맞고 말았다. 기타를 사야 한다.
강토는 공연 때 연주할 노래의 목록을 뽑아 놓았다. 하지만, 하나의 기타로 모든 곡을 연주할 수는 없다. 어떤 기타는 어떤 곡을 연주할 때, 이상한 소리가 나기 때문이다. 항상 완벽을 추구하는 강토는 이런 일을 용납하지 않는다.
최대한 많은 곡을 제대로 연주하려고 할 때, 필요한 기타의 최소 개수를 구하는 프로그램을 작성하시오.
예를 들어, GIBSON으로 1, 2, 3번 곡을 제대로 연주할 수 있고, FENDER로 1, 2, 5번 곡을 제대로 연주할 수 있고, EPIPHONE으로 4, 5번 곡을 제대로 연주할 수 있고, ESP로 1번곡을 제대로 연주할 수 있다면, 세준이는 EPIPHONE과 GIBSON을 사면 최소의 개수로 모든 곡을 연주할 수 있다.
입력
첫째 줄에 기타의 개수 N과 곡의 개수 M이 주어진다. N은 10보다 작거나 같은 자연수이고, M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 기타의 이름과 기타가 연주할 수 있는 곡의 정보가 1번 곡부터 차례대로 주어진다. Y는 연주할 수 있는 것이고, N은 없는 것이다. 기타의 이름은 알파벳 대문자로만 이루어져 있고, 길이는 2 이상, 50 이하이다. 두 기타의 이름이 같은 경우는 없다.
출력
첫째 줄에 필요한 기타의 개수를 출력한다. 만약 연주할 수 있는 곡이 없으면 -1을 출력한다.
문제 풀이
비트마스킹 문제.
곡 수인 M이 최대 50개이므로 모두 탐색하기 위해서 빠른 계산을 할 수 있는 비트마스킹을 사용한다. 각 기타마다 연주할 수 있는 곡을 true, false로 저장하는 것이 아니라 long long 타입의 수로 저장한다. 이 수를 2진수로 변환했을 때 i번째 자리가 1이면 i번째 곡을 연주 할 수 있다는 의미가 된다.
마찬가지로 연주할 곡을 정할 때에도 비트마스킹을 이용하여 저장한다.
아래는 코드.
#include <iostream>
using namespace std;
int N, M;
long long* playLists;
int answer;
int maxCount;
int countBit(long long temp)
{
if (temp == 0)
{
return 0;
}
return temp % 2 + countBit(temp / 2);
}
void backTracking(int index, long long bit, int selectedNum)
{
int bitCount = countBit(bit);
if (bitCount > maxCount) {
maxCount = bitCount;
answer = selectedNum;
}
else if (bitCount == maxCount) {
answer = min(answer, selectedNum);
}
if (index == N)
{
return;
}
backTracking(index + 1, bit | playLists[index], selectedNum + 1);
backTracking(index + 1, bit, selectedNum);
}
int main()
{
cin.tie(NULL);
ios::sync_with_stdio(false);
string str, playList;
cin >> N >> M;
playLists = new long long[N];
answer = -1;
for (int i = 0; i < N; i++)
{
cin >> str >> playList;
playLists[i] = 0;
for (int j = 0; j < M; j++)
{
int bit = 0;
if (playList[j] == 'Y')
{
bit = 1;
}
else
{
bit = 0;
}
playLists[i] = playLists[i] | ((long long) bit << j);
}
}
backTracking(0, 0, 0);
cout << answer << "\n";
return 0;
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준 15353] 큰 수 A+B (2) (C++) (0) | 2024.11.29 |
---|---|
[백준 14569] 시간표 짜기 (C++) (0) | 2024.11.28 |
[백준 2828] 사과 담기 게임 (C++) (0) | 2024.11.25 |
[백준 15904] UCPC는 무엇의 약자일까? (C++) (0) | 2024.11.24 |
[백준 16500] 문자열 판별 (C++) (0) | 2024.11.23 |