문제 : https://algospot.com/judge/problem/read/ALLERGY
알고리즘 문제 해결 전략 p.429
책을 참고하지 않고 코드를 작성함
[알고스팟 STEP.1]
비트마스크를 이용해서 지금까지 음식을 먹을 수 있는 사람들을 저장하고, 모든 사람들이 음식을 먹을 수 있을 때에 음식의 수의 최소값을 출력했다.
*void getInput()
입력을 받는 함수이다.
이름은 names벡터에 따로 저장해두고
FOR(i, n){
cin >> names[i];
}
food번째 음식에 대해 음식을 먹을 수 있는 이름들이 나오면, 그 이름을 갖고 있는 인덱스를 names에서 찾아서 그 값을 비트마스크로 환산하여 allergic[food]에 더했다.
이렇게 하면 food번째 (음식을 먹을 수 있는 사람)번째 자리는 1, (음식을 먹을 수 없는 사람)번째 자리는 0 으로 2진수가 생성된다.
FOR(food, m){
cin >> people;
long long int bit = 0;
FOR(j, people){
cin >> temp;
FOR(k, n){
if(!strcmp(temp.c_str(), names[k].c_str())) { //**strcmp 사용법
bit += (1LL << k);
break;
}
}
}
allergic[food] = bit;
}
모든 사람들이 음식을 먹을 수 있는 경우는 미리 full에 계산해두었다.
full = (1LL<<n)-1;//**비트연산자 int넘어갈때
*void solve(long long int a, int sum, int index)
입력받은 값 들에 대해 문제를 푸는 함수이다.
그냥 0번째 음식 부터 차례대로 넣고/ 안넣고를 반복하여, m개의 음식에 대해 2^m가지 경우의 수를 모두 실행해보았다.
a==full일 때, 지금까지 만든 음식의 수 sum을 best와 비교해서 업데이트 했다.
void solve(long long int a, int sum, int index){
// cout << bitset<50>(a) <<" "<<sum <<"index : "<< index << endl;
if(a==full){
best = min(best, sum);
// cout << "best updated to ... " << best << endl;
}
if(index == m) return;
// index물건 넣음
// cout << index << " 넣음--" << endl;
solve(a|allergic[index], sum+1, index+1);
//index 안 넣음
// cout << index << " 안넣음--" << endl;
solve(a, sum, index+1);
}
[알고스팟 STEP.2]
solve의 첫 줄에, 이미 sum이 best보다 큰 경우 더 이상 시행하지 않는 코드를 추가해서 pruning을 했다.
이미 sum이 best보다 크다면 어차피 그 시행에서 sum은 best보다 작은 값이 나올 수 없으므로 더 이상 실행해보지 않아도 된다.
[최종코드]
// } |
[내가 헤맸던 부분]
- 비트마스크가 int범위를 넘어가서 long long int를 도입해야 했다. 처음에 full을 만들 때 full을 long long int로 선언했음에도 불구하고
full = (1<<n)-1;
이렇게 코드를 작성하면 full이 int범위로 생성되었다.
'알고리즘' 카테고리의 다른 글
algospot :: ARCTIC 남극기지 (0) | 2017.10.23 |
---|---|
algospot :: DARPA DARPA Grand Challenge (0) | 2017.10.22 |
algospot :: BOARDCOVER2 게임판 덮기 2 (0) | 2017.10.21 |
algospot :: STRJOIN 문자열 합치기 (0) | 2017.10.17 |
algospot :: LUNCHBOX 도시락 데우기 (0) | 2017.10.17 |