{*************************************************************************}
{* *}
{* VI Olimpiada Informatyczna *}
{* *}
{* RozwiĄzanie zadania: WODA *}
{* Plik: WOD.PAS *}
{* Autor: Marcin Mucha *}
{*************************************************************************}
const
N_MAX = 100;
M_MAX = 100;
NM_MAX = N_MAX * M_MAX;
H_MAX = 10000;
type
t_coords = record
x, y : byte
end;
t_heap = record
data : array[1..NM_MAX] of t_coords;
size : word;
end;
t_square = record
h : word;
lpath : word { Wysoko† najniľszej scieľki do brzegu lub INFTY. }
end;
p_queue_elem = ^t_queue_elem;
t_queue_elem = record
coords : t_coords;
next : p_queue_elem
end;
t_queue = record
first, last : p_queue_elem;
end;
const
file_in_name = 'wod.in';
file_out_name = 'wod.out';
INFTY = 65535;
var
file_in, file_out : text;
board : array[0..N_MAX + 1, 0..M_MAX + 1] of t_square;
n, m : word;
queue : t_queue;
heap : t_heap;
procedure queue_init( var q : t_queue);
begin
q.first := nil; q.last := nil
end;
procedure queue_put( var q : t_queue; x, y : byte);
var
p : p_queue_elem;
begin
new( p);
p^.coords.x := x;
p^.coords.y := y;
p^.next := nil;
if q.first = nil then
q.first := p
else
q.last^.next := p;
q.last := p
end;
procedure queue_get( var q : t_queue; var x : byte; var y : byte);
var
p : p_queue_elem;
begin
x := q.first^.coords.x;
y := q.first^.coords.y;
p := q.first;
q.first := q.first^.next;
if q.first = nil then
q.last := nil;
dispose( p);
end;
function queue_empty( var q : t_queue) : boolean;
begin
queue_empty := ( q.first = nil)
end;
function height( var c : t_coords) : word;
begin
height := board[c.x][c.y].h
end;
procedure heap_init( var h : t_heap);
begin
h.size := 0
end;
procedure heap_swap( var h : t_heap; i, j : word);
var
c : t_coords;
begin
c := h.data[i];
h.data[i] := h.data[j];
h.data[j] := c
end;
procedure heap_go_down( var h : t_heap);
var
i, smallest : word;
begin
i := 1;
while 2 * i <= h.size do
begin
if ( 2 * i <= h.size) and
( height( h.data[2 * i]) < height( h.data[i])) then
smallest := 2 * i
else
smallest := i;
if ( 2 * i + 1 <= h.size) and
( height( h.data[2 * i + 1]) < height( h.data[smallest])) then
smallest := 2 * i + 1;
if smallest <> i then
begin
heap_swap( h, smallest, i);
i := smallest
end
else
exit
end
end;
procedure heap_add( var h : t_heap; x, y : byte);
var
i : word;
begin
inc( h.size);
i := h.size;
while ( i > 1) and ( board[x][y].h < height( h.data[i div 2])) do
begin
h.data[i] := h.data[i div 2];
i := i div 2
end;
h.data[i].x := x; h.data[i].y := y
end;
procedure heap_remove( var h : t_heap; var x : byte; var y : byte);
begin
x := h.data[1].x; y := h.data[1].y;
h.data[1] := h.data[h.size];
dec( h.size);
heap_go_down( h);
end;
function heap_empty( var h : t_heap) : boolean;
begin
heap_empty := ( h.size = 0)
end;
procedure read_data;
var
i, j : byte;
begin
heap_init( heap);
readln( file_in, n, m);
for i := 0 to n + 1 do
begin
board[i][0].h := INFTY; board[i][0].lpath := INFTY;
board[i][m + 1].h := INFTY; board[i][m + 1].lpath := INFTY
end;
for j := 0 to m + 1 do
begin
board[0][j].h := INFTY; board[0][j].lpath := INFTY;
board[n + 1][j].h := INFTY; board[n + 1][j].lpath := INFTY
end;
for i := 1 to n do
for j := 1 to m do
begin
board[i][j].lpath := INFTY;
read( file_in, board[i][j].h);
heap_add( heap, i, j)
end
end;
procedure find_paths;
var
x, y : byte;
p : p_queue_elem;
procedure adjust_lpath( x, y : byte; value : word);
begin
if ( board[x][y].h <= value) and ( board[x][y].lpath = INFTY) then
begin
board[x][y].lpath := value;
queue_put( queue, x, y)
end
end;
begin
queue_init( queue);
repeat
heap_remove( heap, x, y);
(* Jeli to jest pole brzegowe, *)
(* albo istnieje cieľka do brzegu po polach o maych wysokociach. *)
if ( x = 1) or ( x = n) or ( y = 1) or ( y = m)
or ( board[x - 1][y].lpath < INFTY)
or ( board[x + 1][y].lpath < INFTY)
or ( board[x][y - 1].lpath < INFTY)
or ( board[x][y + 1].lpath < INFTY) then
adjust_lpath( x, y, board[x][y].h);
while not queue_empty( queue) do
begin
queue_get( queue, x, y);
adjust_lpath( x - 1, y, board[x][y].lpath);
adjust_lpath( x + 1, y, board[x][y].lpath);
adjust_lpath( x, y - 1, board[x][y].lpath);
adjust_lpath( x, y + 1, board[x][y].lpath);
end
until heap_empty( heap);
end;
function sum_up : longint;
var
i, j : byte;
sum : longint;
begin
sum := 0;
for i := 1 to n do
for j := 1 to m do
inc( sum, board[i][j].lpath - board[i][j].h);
sum_up := sum;
end;
begin
assign( file_in, file_in_name);
reset( file_in);
read_data;
close( file_in);
find_paths;
assign( file_out, file_out_name);
rewrite( file_out);
write( file_out, sum_up);
close( file_out)
end.