Описание Дано прямоугольное клетчатое поле M×N клеток. Каждая клетка поля покрашена в один из шести цветов, причем левая верхняя и правая нижняя клетки имеют различный цвет. В результате поле разбивается на некоторое количество одноцветных областей: две клетки одного цвета, имеющие общую сторону, принадлежат одной области Правила игры Играют два игрока. За первым игроком закреплена область, включающая левую верхнюю клетку, за вторым - правую нижнюю. Игроки ходят по очереди. Делая ход, игрок перекрашивает свою область:в любой из шести цветов в любой из шести цветов, за исключением цвета своей области и цвета области противника
В результате хода к области игрока присоединяются все прилегающие к ней области выбранного цвета, если такие имеются. Если после очередного хода окажется, что области игроков соприкасаются, то игра заканчивается Задание Напишите программу, которая для каждого из пунктов (А и Б) определяет минимально возможное число ходов, по прошествии которых игра может завершиться. Входные данные Цвета пронумерованы цифрами от 1 до 6. Первая строка входного файла содержит целые числа M и N - размеры поля (1 M,N 50). Далее следует описание раскраски поля - M строк по N цифр (от 1 до 6) в каждой без пробелов. Первая цифра файла соответствует цвету левой верхней клетки игрового поля. Количество одноцветных областей не превосходит 50 Выходные данные В выходной файл выведите искомое количество ходов для каждого из пунктов. Если ваша программа решает только один из пунктов, выведите произвольное целое число в качестве ответа на другой пункт Например: TOGOTO.IN 4 3 122 221 143 132 TOGOTO.OUT 3 4 Комментарии Идеи и метод решения задачи авторами не комментировались Решение {$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R+,S+,T-,V+,X+,Y+} {$M 65384,0,655360} {.$DEFINE DEBUG} program togoto; type table = array [0..51, 0..51] of integer; const dx : array [1..4] of integer = (1, -1, 0, 0); dy : array [1..4] of integer = (0, 0, 1, -1); var t : table; i, j : integer; a_result, b_result : integer; m, n : integer; temp : string; qx, qy, qc : array [1..2500] of integer; qh, qt : integer; function ok(a, b : integer): boolean; begin ok := false; if (a<1) or (a > m) or (b < 1 ) or (b > n) then exit; ok := true; end; {Получаем и достаем из очереди} function put(a, b, c : integer) : boolean; begin put := false; if not ok(a, b) then exit; put := true; qx[qh] := a; qy[qh] := b; qc[qh] := c; inc(qh); if qh > 2500 then qh := 1; end; procedure get(var a, b, c : integer); begin a := qx[qt]; b := qy[qt]; c := qc[qt]; inc(qt); if qt > 2500 then qt := 1; end; {-----------------------------------} function min (a, b : integer) : integer; begin if a < b then min := a else min := b; end; procedure Fill(a, b, cur : integer; var l : table); procedure reFill(a, b : integer); var i : integer; begin if not put(a, b, cur) then exit; l[a][b] := cur; for i := 1 to 4 do if (l[a + dx[i]][b+dy[i]] = 16448) and (t[a][b] = t[a+dx[i]][b+dy[i]]) then reFill(a + dx[i], b + dy[i]); end; begin ReFill(a, b); end; procedure find(sa, sb : integer; Var l : table); var cur : integer; i, a,b, c : integer; begin cur := 0; fill(sa, sb, 0, l); while qt <> qh do begin get(a, b, c); for i := 1 to 4 do if l[a + dx[i] ] [ b + dy[i]] = 16448 then fill(a + dx[i], b + dy[i], c+1, l); end; end; procedure solve_a; var p1, p2 : table; i, j, k : integer; begin qh := 1; qt := 1; a_result := maxint; FillChar(p1, sizeof(p1), 64); FillChar(p2, sizeof(p2), 64); find(1, 1, p1); find(m, n, p2); for i := 1 to m do for j := 1 to n do for k := 1 to 4 do case p1[ i ][ j ] - p2[ i + dx[k] ] [j + dy[k]] of 0, 1: a_result := min(p1[i][j] + p2[i+dx[k]] [j+dy[k]], a_result); end; end; procedure solve_b; var area : Table; cur : integer; n_area : integer; color : array [1..50] of integer; pl : array [1..2] of table; lk : Table; i,j,k,l, t : integer; procedure upd(var a : integer; b : integer); begin a:= min(a, b); end; label quit; begin FillChar(area, sizeof(area), 64); b_result := -1; cur := 0; for i := 1 to m do for j := 1 to n do begin if area[i][j] = 16448 then begin inc(cur); color[cur] := togoto.t[i][j]; Fill(i, j, cur, area); end; end; if cur > 50 then begin writeln('Number of areas exceeds 50 (',cur,')'); halt; end; qh := 1; qt := 1; n_area := cur; fillchar(lk, sizeof(lk), 0); for i := 1 to m do for j := 1 to n do for k := 1 to 4 do if ok(i+dx[k], j + dy[k]) then begin lk[area[i][j]][area[i+dx[k]][j + dy[k]]] := 1; lk[area[i+dx[k]][j + dy[k]]][area[i][j]] := 1; end; for i := 1 to n_area do lk[i][i] := 1; FillChar(pl, Sizeof(pl), 64); pl[1][1][area[m][n]] := 0; pl[2][1][area[m][n]] := 1; for T := 0 to 2500 do for i := 1 to n_area do for j := 1 to n_area do begin if (pl[1][i][j] = T) and (lk[i][j]=1) then begin b_result := pl[1][i][j]; goto quit; end; if (pl[2][i][j] = T) and (lk[i][j]=1) then begin b_result := pl[2][i][j]; goto quit; end; if pl[1][i][j] = T then begin for k := 1 to n_area do if (lk[i][k]=1) then begin if color[k]<>color[j] then upd(pl[2][k][j], T+1) else for l := 1 to n_area do if lk[j][l]=1 then upd(pl[2][k][l], T+3); end; end; if pl[2][i][j] = T then begin for k := 1 to n_area do if (lk[j][k]=1) then begin if color[k]<>color[i] then upd(pl[1][i][k], T+1) else for l := 1 to n_area do if lk[i][l]=1 then upd(pl[1][l][k], T+3); end; end; {if} end; {for j} quit: asm nop; end; end; Begin assign(input, 'togoto.in'); reset(input); readln(m, n); for i := 1 to m do begin readln(temp); for j := 1 to n do t[i][j] := ord(temp[j]) - ord('0'); end; close(input); assign(input, ''); reset(input); solve_a; solve_b; {$IFNDEF DEBUG} assign(output, 'togoto.out'); rewrite(output); {$ENDIF DEBUG} writeln(a_result); writeln(b_result); close(input);close(output) End.
|