10999. Кребс
Кребс – это игра, в которой следует из квадратных
пластин с написанными на них буквами складывать слова. Составлять можно только
слова, которые присутствуют в словаре. Каждая пластина кроме буквы содержит
также количество очков, которое дается игроку при ее использовании в слове.
Цена сложенного слова равна сумме очков пластин, из которых оно сложено.
Процесс игры состоит в том, что игроку дают определенный набор пластин, из
которых он должен сложить одно слово с наибольшей ценой. В задаче следует по
заданному словарю и набору пластин составить слово с наибольшей ценой.
Вход. Первая
строка содержит количество слов n (1 £ n £ 100000) в словаре. Следующие n
строк описывают имеющийся словарь. Следующая строка содержит количество игр m (1 £ m £ 1000), которое следует сыграть.
Каждая игра состоит из количества имеющихся на руках пластин p (1 £ p £ 10) , за которым идут p строк, описывающих пластины игрока в формате: <буква> <количество очков>. Буквы являются прописными, количество очков у каждой буквы не меньше 0 и
не больше 10.
Выход. Для каждой игры вывести слово с наибольшей
ценой, которое можно сложить из имеющихся пластин.
2
abcd
hgfe
1
10
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
i 9
j 10
Пример выхода
26
структуры данных + перебор
Словарь для всех игр одинаковый,
хранить будем его в структуре “множество” set<string>. Перед запоминанием слова отсортируем его буквы. Поскольку
количество пластин у игрока в каждой игре не более 10, то полным перебором
генерируем все слова, которые он может составить (все подмножества из имеющихся
букв на пластинах), проверяем, принадлежит ли это слово словарю, и если да – то
ищем среди всех таких слов то, которое имеет наибольшую цену.
В переменной s храним все слова словаря. Символьный массив bufer используем при чтении строк, буквы игрока храним в
массиве letter, а их соответствующие значения в
массиве v.
set<string> s;
char bufer[50], letter[11];
int v[11];
Читаем словарь, состоящий из n слов. Слова читаем в символьный массив
bufer, преобразовываем их в тип string,
сортируем буквы и заносим в множество s.
scanf("%d\n",&n);
for(i = 0; i < n; i++)
{
gets(bufer); s_temp = (string)bufer;
sort(s_temp.begin(),s_temp.end());
s.insert(s_temp);
}
Читаем количество игр m.
scanf("%d",&m);
while(m--)
{
Читаем набор пластин игрока.
Игрок имеет пластин, буквы заносим в массив letter, а соостветствующие им очки
– в целочисленный массив v.
scanf("%d\n",&p);
for(i = 0; i
< p; i++)
scanf("%c %d\n",&letter[i],&v[i]);
В переменной res будем искать наибольшую цену слова. Все подмножества из p пластин (кроме пустого) генерируем перебирая значения i от 1 до 2p
– 1 . Если j - ый бит числа i равен 1, то j - ую пластину включаем в текущее подмножество. Сортируем буквы полученного подмножества, хранящегося в строке s_temp. В переменной Sum хранится его цена. Ищем слово s_temp в словаре при помощи метода find класса string. Если слово
найдено и его цена больше текущей, хранящейся в переменной res, то полагаем res = Sum. Перебрав все подмножества (все
возможные слова, которые можно составить из имеющихся пластин), выводим
значение переменной res.
res = 0;
for(i = 1; i
< (1 << p); i++)
{
Sum = 0; s_temp = "";
for(j = 0;
j < p; j++)
if (i
& (1 << j)) Sum += v[j],s_temp += letter[j];
sort(s_temp.begin(),s_temp.end());
if
((s.find(s_temp) != s.end()) && (Sum > res)) res = Sum;
}
printf("%d\n",res);
}