|
ЗАДАЧИ
problems.ru |
О проекте
|
Об авторах
|
Справочник
Каталог по темам | по источникам | |
|
|
Задача 98721
УсловиеУ Пети имеется неограниченный набор красных, синих и зеленых плиток размером 1 * 1. Он выбирает ровно N плиток и выкладывает их в полоску. Например, при N = 10 она может выглядеть следующим образом:
(буквой К обозначена красная плитка, С синяя, З зеленая). После этого Петя заполняет следующую таблицу:
В клетке на пересечении строки, отвечающей цвету А, и столбца, отвечающего цвету Б, он записывает "Y", если в его полоске найдется место, где рядом лежат плитки цветов А и Б и "N" в противном случае. Считается, что плитки лежат рядом, если у них есть общая сторона. (Очевидно, что таблица симметрична относительно главной диагонали если плитки цветов А и Б лежали рядом, то рядом лежали и плитки цветов Б и А.) Назовем такую таблицу диаграммой смежности данной полоски.
Формат входных данных РешениеПрежде всего вспомним задачу "Взрывоопасность". Идея, положенная в основу ее решения, заработает и здесь. Итак, разбиваем все полоски из плиток на 64 группы (соответственно количеству матриц смежности), нумеруя их следующим образом. Берем все возможные матрицы смежности (всего их 64) и выписываем 6 букв из матриц подряд (то, что ниже главной диагонали, нас не интересует, так как никакой информации не несет). Меняем "Y" на "1", а "N" - на "0" и получаем двоичный код нашей группы. Каждую из групп дополнительно разобьем на три подгруппы, в зависимости от плитки, лежащей справа. Теперь наращиваем полоску вновь справа. Прописать вручную все 576 (64 группы, 3 подгруппы, 3 наращиваемых цвета) возможных комбинаций невозможно. К счастью, рассматривать группы нет необходимости, если воспользоваться битовой арифметикой. Достаточно рассмотреть всевозможные пары крайних плиток и определить смежность, которую они образуют. Она способна в каждой группе либо превратить "N" в "Y" (если ранее не встречалась), либо ничего не изменить. Определив позицию возможного изменения, создаем маску, в которой все биты равны нулю, кроме изменяемого. Остается только применить полученную маску к каждой группе (путем логического "или"). Не стоит забывать, что все эти операции производятся над длинными числами. Function Check(i, j : shortint; s : integer) : integer;
var r, k : integer;
begin
if i > j then begin k := j; j := i; i := k end;
if i = 2 then j := j + 2;
if i = 3 then j := j + 3;
r := 1;
for k := 1 to j - 1 do r := r * 2;
Check := s or r; {применяем маску r к группе s}
end;
...
for i := 0 to 63 do
begin
for l := 1 to 3 do
for k := 1 to 3 do
begin
NewS := Check(l, k, i);{определяем новый номер группы}
Add(Na[News][k], A[i][l], Na[NewS][k]);{и добавляем в нее все, что было в старой}
{Na[News][k] := Na[News][k] + A[i][l] - аналог в обычной арифметике}
end
end;
Источники и прецеденты использования |
|
© 2004-...
МЦНМО
(о копирайте)
|
Пишите нам
|
|