Подразделы

Другие разделы

Дата и время

19/12/2024 20:52:26

Авторизация

Имя:
Пароль:
Зарегистрироваться
Восстановить пароль
 

printРазбор задачи D. Пизанская башня

Тема: динамическое программирование
Сложность: ниже среднего

1 способ: вывод рекуррентной формулы
Вручную для `n` от 1 до 5 находим минимальное количество перекладываний.
n12345
кол-во ходов `m`135915
Далее, видим, что зависимость можно описать формулой `m_i\ =\ m_{i-2}+m_{i-1}+1`.
var n,i:integer;
  m:array[1..40]of int64;
begin
  read(n);
  m[1]:=1;
  m[2]:=3;
  for i:=1 to n do
    m[i]:=m[i-2]+m[i-1]+1;
  writeln(m[n]);
end.
2 способ: запоминающая функция
Чтобы переложить `n` дисков со столбика `a` на столбик `b`, нужно сначала переложить `n-1` диск на столбик `6-a-b`, затем переложить `n`-й диск на столбик `b`, затем все диски со столбика `6-a-b` на столбик `b`. Чтобы повторно не вычислять результат функции количества перекладываний для некоторого набора аргументов (`n`, `a`, `b`), функция должна запоминать в массиве результаты предыдущих вычислений. Размерность массива для запоминания должна совпадать с количеством аргументов функции и областью определения аргументов.
var n:integer;
  _nmoves:array[1..40,1..3,1..3] of int64; { для запоминания результата }
function nmoves(n,a,b:integer):int64;
begin
  if _nmoves[n,a,b]=0 then
    if (n=1) or (a=2) then
      _nmoves[n,a,b]:=1
    else
      _nmoves[n,a,b]:=nmoves(n-1,a,6-a-b)+1+nmoves(n-1,6-a-b,b);
  nmoves:=_nmoves[n,a,b]
end;
begin
  read(n);
  writeln(nmoves(n,1,3));
end.
loading