Rambler's Top100

Скачать программы    Все программы автора

КАЗИНО

 В верхнем левом углу прямоугольного поля размерами N´M размещается игральний кубик, разворот которого изображен на рисунке. Кубик ориентирован так, что передней грани соответствует единица, а слева находится грань, которой соответствует двойка. Клетки поля квадратные, их размеры совпадают с размерами грани кубика.

Кубик может двигаться по полю, переворачиваясь через одно из ребер, и попадать при этом в соседнюю снизу, сверху, справа или слева клетку поля. Например, если из начального состояния кубик двигается направо, то передней станет грань с двойкой, а если вниз — то с тройкой. Кубик не может выходить за пределы поля.

Задание

Напишите программу CASINO, которая по информации о поле находит один из возможных путей кубика из верхнего левого угла в нижний правый угол поля. При этом необходимо найти такой путь, чтобы передняя грань кубика в целевой клетке имела максимальное возможное значение. Кубик может посещать каждую клетку поля несколько раз.

Входные данные

Первая строка входного файла CASINO.DAT содержит два натуральных числа N и M (2£N, M£50), которые определяют высоту и ширину поля соответственно. Далее задается поле, которое представлено N строками, каждая из которых состоит из M чисел, каждое из которых равно 0 либо 1. В случае, когда клетке поля соответствует число 1, кубику запрещено посещать данную клетку. В противном случае эта клетка может встречаться в пути кубика. Начальной клетке всегда соответствует число 0.

Выходные данные

Первая строка выходного файла CASINO.SOL должна содержать натуральное число W — длину найденого пути. Далее в файле должны находиться W строк, каждая из которых задает координату клетки поля на текущем шаге. Координата представляет собой пару натуральных чисел: номер строки и номер столбца клетки поля.

В случае, когда искомого пути не существует, выходной файл должен содержать строку с числом -1.

 

Пример входных и выходных данных

CASINO.DAT

CASINO.SOL

3 2

0 1

0 0

0 0

3

2 1

2 2

3 2

{ Problem: CASINO}

program casino;

const

MAX_N = 50; {maximum field size}

STATE_NUM = 24; {the number of possible brick positions}

FILE_IN = 'casino.dat';

FILE_OUT = 'casino.sol';

type

TDirection = (DIR_UP, DIR_RIGHT, DIR_DOWN, DIR_LEFT);

TState = byte; {1..STATE_NUM;}

TPosition = record

row : byte;

column : byte;

end;

TMarks = array[1..STATE_NUM] of boolean;

const

States : array[1..STATE_NUM, 1..2] of integer = (

{ 1} (1,2), { 2} (1,3), { 3} (1,4), { 4} (1,5),

{ 5} (2,1), { 6} (2,3), { 7} (2,4), { 8} (2,6),

{ 9} (3,1), {10} (3,2), {11} (3,5), {12} (3,6),

{13} (4,1), {14} (4,2), {15} (4,5), {16} (4,6),

{17} (5,1), {18} (5,3), {19} (5,4), {20} (5,6),

{21} (6,2), {22} (6,3), {23} (6,4), {24} (6,5));

Sides : array[1..6, 1..4] of integer = (

(2, 3, 5, 4),

(1, 4, 6, 3),

(1, 2, 6, 5),

(1, 5, 6, 2),

(1, 3, 6, 4),

(2, 4, 5, 3)

); 

type

TQueueElement = record

pos : TPosition;

state : TState;

prev : Word;

end;

PQueueElement = ^TQueueElement;

TVec = array[1..5] of TQueueElement;

TQueue = array[1..MAX_N*MAX_N*STATE_NUM div 5] of ^TVec;

var

n : Integer; {field height}

m : Integer; {field width}

field : array[1..MAX_N, 1..MAX_N] of Boolean;

waves : array[1..MAX_N, 1..MAX_N] of TMarks;

pqueue : ^TQueue;

qSize : Integer;

qCurr : Integer;

currSolId : integer;

solFound : Boolean;

{-------------------------------------------------------------}

{Dynamic init}

procedure DynInit;

var

i : integer;

begin

new(pqueue);

for i:=1 to MAX_N*MAX_N*STATE_NUM div 5 do

new(pqueue^[i]);

end;

{Dynamic dispose}

procedure DynDispose;

var

i : integer;

begin

for i:=1 to MAX_N*MAX_N*STATE_NUM div 5 do

Dispose(pqueue^[i]);

Dispose(pqueue);

end;

{Dynamic work}

procedure GetQueueElement(x : Word; var ppos : PQueueElement);

begin

ppos := @pqueue^[ ( (x-1) div 5 ) + 1 ]^[ ( (x-1) mod 5 ) + 1];

end;

{=============================================================}

procedure Init;

var

fin : Text;

i, j : Integer;

value : Integer;

begin

Assign(fin, FILE_IN);

Reset(fin);

ReadLn(fin, n, m);

FillChar(waves, sizeof(waves), false);

for i:=1 to n do

begin

for j:=1 to m do

begin

Read(fin, value);

if value = 0

then field[i,j]:=true

else field[i,j]:=false;

end;

end;

Close(fin);

solFound := false;

currSolId := 0;

DynInit;

end; 

function CanMove(pos : TPosition; dir : TDirection) : boolean;

begin

CanMove := false;

if (pos.row = 1) and (dir = DIR_UP) then exit;

if (pos.row = n) and (dir = DIR_DOWN) then exit;

if (pos.column = 1) and (dir = DIR_LEFT) then exit;

if (pos.column = m) and (dir = DIR_RIGHT) then exit;

if (dir = DIR_UP) and (not field[pos.row-1, pos.column]) then exit;

if (dir = DIR_DOWN) and (not field[pos.row+1, pos.column]) then exit;

if (dir = DIR_LEFT) and (not field[pos.row, pos.column-1]) then exit;

if (dir = DIR_RIGHT) and (not field[pos.row, pos.column+1]) then exit;

CanMove := true;

end;

procedure GetStateByPair(up, left : integer; var state : TState);

var

i : integer;

begin

for i:=1 to STATE_NUM do

if (States[i,1] = up) and (States[i,2] = left) then

begin

state := i;

exit;

end;

end;

function CubeSide(upper, side, many : integer) : integer;

var

i : integer;

begin

for i:=1 to 4 do

if Sides[upper, i] = side then

break;

if (i+many) mod 4 = 0

then CubeSide := Sides[upper, 4]

else CubeSide := Sides[upper, (i+many) mod 4];

end;

procedure MoveBrick(var state : TState; dir : TDirection);

var

up, left : integer;

nu, nl : integer;

begin

up := States[state, 1];

left := States[state, 2];

case dir of

DIR_UP :

begin

nl:=left;

nu:=CubeSide(left,up,1);

end;

DIR_RIGHT :

begin

nl:=CubeSide(left,up,2);

nu:=left;

end;

DIR_LEFT :

begin

nl:=up;

nu:=CubeSide(up,left,2);

end;

DIR_DOWN :

begin

nl:=left;

nu:=CubeSide(left,up,3);

end;

end;

GetStateByPair(nu, nl, state);

end;

procedure Move(var pos : TPosition; var state : TState; dir : TDirection);

begin

case dir of

DIR_UP : Dec(pos.row);

DIR_RIGHT : Inc(pos.column);

DIR_LEFT : Dec(pos.column);

DIR_DOWN : Inc(pos.row);

end;

MoveBrick(state, dir);

end;

procedure Run;

var

dir : TDirection;

pos, newPos : TPosition;

state, newState : TState;

pqe, pqe1, pqe2, pqe3 : PQueueElement;

begin

GetQueueElement(1, pqe);

pqe^.pos.row:=1;

pqe^.pos.column:=1;

pqe^.state:=1;

pqe^.prev:=0;

qSize:=1;

qCurr:=1;

waves[1,1][1] := true;

while ((qSize>=qCurr) and (not solFound)) do

begin

GetQueueElement(qCurr, pqe1);

pos := pqe1^.pos;

state := pqe1^.state;

for dir:=DIR_UP to DIR_LEFT do

if CanMove(pos, dir) then

begin

newPos := pos;

newState := state;

Move(newPos, newState, dir);

if not waves[newPos.row, newPos.column][newState] then

begin

{ Add the element to the queue }

Inc(qSize);

waves[newPos.row, newPos.column][newState] := true;

GetQueueElement(qSize, pqe2);

pqe2^.prev := qCurr;

pqe2^.pos := newPos;

pqe2^.state := newState;

end;

if (currSolId<>0) then

GetQueueElement(currSolId, pqe3);

if ((currSolId = 0) or (newState > pqe3^.state)) and

(newPos.row = n) and

(newPos.column = m) then

begin

currSolId := qSize;

if newState >= 21 then

begin

{ Solution has been found }

solFound := true;

exit;

end;

end;

end;

Inc(qCurr);

end;

if currSolId <> 0 then

solFound := true;

end;

procedure Done;

var

fout : Text;

number : integer;

prev, curr, next : integer;

i : integer;

pqe : PQueueElement;

begin

Assign(fout, FILE_OUT);

Rewrite(fout);

if not solFound then

WriteLn(fout, '-1')

else

begin

GetQueueElement(currSolId, pqe);

next := currSolId;

curr := pqe^.prev;

number := 0;

while curr <> 0 do

begin

inc (number);

GetQueueElement(curr, pqe);

prev := pqe^.prev;

pqe^.prev := next;

next := curr;

curr := prev;

end;

WriteLn(fout, number);

GetQueueElement(1, pqe);

curr:=pqe^.prev;

for i:=1 to number do

begin

GetQueueElement(curr, pqe);

WriteLn(fout, pqe^.pos.row, ' ', pqe^.pos.column);

curr := pqe^.prev;

end;

end;

Close(fout);

DynDispose;

end;

begin

Init;

Run;

Done;

end.

Белорусский рейтинг MyMinsk.com Сайты беларуси Регистр "ЗУБР" Каталог на TIGA.BY, а также  новости, работа, объявления, фото и многое другое Рейтинг@Mail.ru Rambler's Top100 Белорусский каталог программ
Hosted by uCoz