[문제 링크]

 

1062번: 가르침

첫째 줄에 단어의 개수 N과 K가 주어진다. N은 50보다 작거나 같은 자연수이고, K는 26보다 작거나 같은 자연수 또는 0이다. 둘째 줄부터 N개의 줄에 남극 언어의 단어가 주어진다. 단어는 영어 소문

www.acmicpc.net


https://onlytrying.tistory.com/34?category=808917

4달전 완전탐색을 공부할 때 한번 푼적이 있는 문제였다.

 

알파벳이 a~z 까지 총 26개 존재하기 때문에 32bit인 int형의 2진수로 a~z 까지 알파벳을 배웠는지 안배웠는지 여부를 표현할 수 있다.

 

따라서 비트마스크를 사용할 수 있다는 것을 알 수 있으며, 이를 사용하여 더 효율적인 알고리즘으로 재구현하였다.

 

핵심은 입력받은 단어에 포함된 알파벳을 OR 연산을 통해 int형 변수 word 에 저장함으로써

배운 알파벳의 정보를 가지고 있는 learn과 AND 연산하여 가능 불가능 여부를 O(1) 에 확인할 수 있다는 것이다.


#include <iostream>
#include <string>
using namespace std;

int learn, word[50];

int max(int a, int b) { return a > b ? a : b; }

int DFS(int start, int N, int K, int learning)
{
	int ret = 0;

	if (learning == K)
	{
		for (int i = 0; i < N; i++)
			if ((word[i] & learn) == word[i]) 
				ret++;

		return ret;
	}

	for (int i = start; i < 26; i++)
	{
		if ((learn & (1 << i)) == 0)
		{
			learn |= (1 << i);
			ret = max(ret, DFS(i + 1, N, K, learning + 1));
			learn &= ~(1 << i);
		}
	}

	return ret;
}

int main(void)
{
	learn |= 1 << ('a' - 'a');
	learn |= 1 << ('c' - 'a');
	learn |= 1 << ('i' - 'a');
	learn |= 1 << ('n' - 'a');
	learn |= 1 << ('t' - 'a');

	int N, K;
	cin >> N >> K;

	for (int i = 0; i < N; i++)
	{
		string str;
		cin >> str;

		for (int j = 0; j < str.length(); j++)
			word[i] |= (1 << (str[j] - 'a'));
	}
		
	if (K < 5 || K == 26)
		cout << (K == 26 ? N : 0) << endl;
	else
		cout << DFS(0, N, K, 5) << endl;

	return 0;
}

알고리즘 200일 프로젝트 - 134 day

'알고리즘 > BOJ' 카테고리의 다른 글

백준 2178번: 미로 탐색  (0) 2020.09.19
백준 1786번: 찾기  (0) 2020.08.24
백준 2212번: 센서  (0) 2020.08.19
백준 1041번: 주사위  (0) 2020.08.17
백준 1439번: 뒤집기  (0) 2020.08.17

+ Recent posts