ЗАДАЧИ
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-...
МЦНМО
(о копирайте)
|
Пишите нам
|