printРешение

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

Текущее состояние комнаты можно представить как целое число из `N` x `N` бит, если валун находится в `(i,j)`-й клетке комнаты, то `((i-1)*N+j-1)`-й бит в этом числе установлен в 1, иначе – в 0. Для преобразования из позиции в число и обратно можно использовать следующие подпрограммы:
type position=array[1..4,1..4]of char;

function encode(const pos:position):integer;
var i,j,k,p:integer;
begin
  p:=0;
  k:=1;
  for i:=1 to n do
    for j:=1 to n do
    begin
      if pos[i][j]='@' then
        p:=p or k;
      k:=k*2;
    end;
  encode:=p;
end;
procedure decode(p:integer; var pos:position);
var i,j,k:integer;
begin
  k:=1;
  for i:=1 to n do
    for j:=1 to n do
    begin
      if (p and k)<>0 then
        pos[i][j]:='@'
      else
        pos[i][j]:='.';
      k:=k*2;
    end;
end;
Далее можно воспользоваться алгоритмом поиска в ширину. В массиве q хранится очередь из позиций, которые нужно обработать, q1 – индекс первого элемента в очереди, q2 – индекс первого свободного элемента. В массиве h записываем количество ходов, которое необходимо, чтобы получить эту позицию из начальной. Если позиция i еще не была достигнута, в h[i] храним `-1`.
const undef=-1;
var q,h:array[0..65535]of integer;
    pos:position;
    n,p,i,j,st,fn,q1,q2:integer;
...
procedure movestone(i1,j1,i2,j2:integer);
var np:integer;
begin
  if (i2<1) or (i2>n) or (j2<1) or (j2>n) then exit;
  if pos[i2][j2]<>'.' then exit;
  pos[i2][j2]:='@'; {двигаем валун}
  pos[i1][j1]:='.';
  np:=encode(pos);
  if h[np]=undef then {позиция ранее не достигалась } 
  begin {добавляем ее в очередь}
    h[np]:=h[p]+1;
    q[q2]:=np;
    inc(q2);
  end;
  pos[i2][j2]:='.'; {двигаем валун обратно}
  pos[i1][j1]:='@';  
end;
procedure readpos;
var i,j:integer;
begin
  for i:=1 to n do
  begin
    for j:=1 to n do
      read(pos[i][j]);
    readln;
  end;
end;
...
begin
  readln(n)
  readpos(pos);
  st:=encode(pos);
  readpos(pos);
  fn:=encode(pos);
  for i:=0 to 65535 do
    h[i]:=undef;
  h[st]:=0;
  q[0]:=st;
  q1:=0;
  q2:=1;
  while q1<q2 do
  begin
    p:=q[q1];
    inc(q1);
    decode(p,pos);
    for i:=1 to n do
      for j:=1 to n do
      if pos[i][j]='@' then
      begin {пытаемся сдвинуть валун во всех направлениях}
        movestone(i,j,i-1,j);
        movestone(i,j,i+1,j);
        movestone(i,j,i,j-1);
        movestone(i,j,i,j+1);
      end;
  end;
  writeln(h[fn]);
end.
loading