ЗАДАЧИ
problems.ru
О проекте | Об авторах | Справочник
Каталог по темам | по источникам |
К задаче N

Проект МЦНМО
при участии
школы 57
Задача 98834
Тема:    [ Нерекурсивная генерация объектов ]
Сложность: 4
Классы:
В корзину
Прислать комментарий

Условие

Перечислить все последовательности длины n из чисел 1..k в таком порядке, чтобы каждая следующая отличалась от предыдущей в единственной цифре, причём не более, чем на 1.

Решение

Рассмотрим прямоугольную доску ширины n и высоты k. На каждой вертикали будет стоять шашка. Таким образом, положения шашек соответствуют последовательностям из чисел 1..k длины n (s-ый член последовательности соответствует высоте шашки на s-ой вертикали). На каждой шашке нарисуем стрелочку, которая может быть направлена вверх или вниз. Вначале все шашки поставим на нижнюю горизонталь стрелочкой вверх. Далее двигаем шашки по такому правилу: найдя самую правую шашку, которую можно подвинуть в направлении (нарисованной на ней) стрелки, двигаем её на одну клетку в этом направлении, а все стоящие правее неё шашки (они упёрлись в край) разворачиваем кругом. Ясно, что на каждом шаге только одна шашка сдвигается, --е один член последовательности меняется на 1. Докажем индукцией по n, что проходятся все последовательности из чисел 1..k. Случай n=1 очевиден. Пусть n>1. Все ходы поделим на те, где двигается последняя шашка, и те, где двигается не последняя. Во втором случае последняя шашка стоит у стены, и мы её поворачиваем, так что за каждым ходом второго типа следует k-1 ходов первого типа, за время которых последняя шашка побывает во всех клетках. Если мы теперь забудем о последней шашке, то движения первых n-1 по предположению индукции пробегают все последовательности длины n-1 по одному разу; движения же последней шашки из каждой последовательности длины n-1 делают k последовательностей длины n. В программе, помимо последовательности x[1]..x[n], будем хранить массив d[1]..d[n] из чисел +1 и -1 (+1 соответствует стрелке вверх, -1 — стрелке вниз). Начальное состояние: x[1]=...=x[n]=1; d[1]=...=d[n]=1. Приведём алгоритм перехода к следующей последовательности (одновременно выясняется, возможен ли переход — ответ становится значением булевской переменной p).

        {если можно, сделать шаг и положить p := true, если нет,
         положить p := false }
        i := n;
        while (i > 1) and
        | (((d[i]=1) and (x[i]=n)) or ((d[i]=-1) and (x[i]=1)))
        |   do begin
        | i:=i-1;
        end;
        if (d[i]=1 and x[i]=n) or (d[i]=-1 and x[i]=1) then begin
        | p:=false;
        end else begin
        | p:=true;
        | x[i] := x[i] + d[i];
        | for j := i+1 to n do begin
        | | d[j] := - d[j];
        | end;
        end;

Замечание. Для последовательностей нулей и единиц возможно другое решение, использующее двоичную систему. (Именно оно связывается обычно с названием " коды Грея".) Запишем подряд все числа от 0 до 2n - 1 в двоичной системе. Например, для n = 3 напишем:

000    001    010    011    100    101    110    111

Затем каждое из чисел подвергнем преобразованию, заменив каждую цифру, кроме первой, на её сумму с предыдущей цифрой (по модулю 2). Иными словами, число a1, a2,..., an преобразуем в  $ \lessmskips$1mua1, a1 + a2, a2 + a3,..., an - 1 + an (сумма по модулю 2). Для n = 3 получим:

000    001    011    010    110    111    101    100

Легко проверить, что описанное преобразование чисел обратимо (и тем самым даёт все последовательности по одному разу). Кроме того, двоичные записи соседних чисел отличаются заменой конца 011...1 на конец 100...0, что — после преобразования — приводит к изменению единственной цифры.

Источники и прецеденты использования

книга
Автор А.Шень
Название Программирование: теоремы и задачи
Издательство МЦНМО
Издание второе
Год издания 2004
глава
Номер 2
Название Порождение комбинаторных объектов
параграф
Номер 5
Название Коды Грея и аналогичные задачи
задача
Номер 2.5.1

© 2004-... МЦНМО (о копирайте)
Пишите нам

Проект осуществляется при поддержке Департамента образования г.Москвы и ФЦП "Кадры" .