program ioi94day1prb2ver1(input, output, inp, out) ; { Tom Verhoeff, Eindhoven University of Technology } { General Section } const Test = true ; var inp, out: text ; procedure Init ; begin if Test then writeln('IOI''94 - Day 1 - Problem 2: The Castle') ; assign(inp, 'input.txt') ; reset(inp) ; assign(out, 'output.txt') ; rewrite(out) ; if Test then writeln('Initialized') end { Init } ; procedure Fini ; begin close(inp) ; close(out) end { Fini } ; { Problem Specific Section } const MaxM = 50 ; MaxN = 50 ; type Row = 1..MaxM ; Column = 1..MaxN ; Direction = (west, north, east, south) ; Module = record wall: array [Direction] of boolean ; nr: integer ; { room number, -1 if unknown } end { Module } ; var M: Row ; N: Column ; Map: array [Row, Column] of Module ; procedure ReadInput ; { read M, N, and Map ; initialize room numbers to -1 } var r: Row ; c: Column ; w: integer ; d: Direction ; begin readln(inp, M, N) ; if Test then writeln('Number of rows is ', M:1, ', number of columns ', N:1) ; for r := 1 to M do begin for c := 1 to N do with Map[r, c] do begin read(inp, w) ; { w encodes the walls of module Map[r, c] } for d := west to south do begin wall[d] := odd(w) ; w := w div 2 end { for d } ; nr := -1 end { for c with Map } ; readln(inp) end { for r } ; if Test then writeln('Input read') ; end { ReadInput } ; procedure WriteCastle ; { write Map to output } var r: Row ; c: Column ; begin for c := 1 to N do with Map[1, c] do if wall[north] then write(' _') else write(' ') ; writeln ; for r := 1 to M do begin for c := 1 to N do with Map[r, c] do begin if (c = 1) then if wall[west] then write('|') else write(' ') ; if wall[south] then write('_') else write(' ') ; if wall[east] then write('|') else write(' ') end { for c with Map } ; writeln end { for r } end { WriteCastle } ; type RoomNumber = 0..MaxM*MaxN ; var rooms: RoomNumber ; { number of rooms completely painted } procedure PaintMap ; { paint the map } procedure PaintRoom(r: Row; c: Column) ; { if Map[r, c] is unpainted then paint it and all modules connected to it } begin with Map[r, c] do if nr = -1 then begin nr := rooms ; if not wall[west] then PaintRoom(r, c-1) ; if not wall[north] then PaintRoom(r-1, c) ; if not wall[east] then PaintRoom(r, c+1) ; if not wall[south] then PaintRoom(r+1, c) end { if } end { PaintRoom } ; var r: Row ; c: Column ; begin rooms := 0 ; for r := 1 to M do for c := 1 to N do if Map[r, c].nr = -1 then begin PaintRoom(r, c) ; rooms := succ(rooms) end { if } end { PaintMap } ; procedure WriteColors ; { write Map colors to output } var r: Row ; c: Column ; begin for r := 1 to M do begin for c := 1 to N do write(Map[r, c].nr:2) ; writeln end { for r } end { WriteColors } ; var area: array[RoomNumber] of integer ; { area[n] is area of room nr. n } maxarea: integer ; { maximum room area } procedure MeasureRooms ; var r: Row ; c: Column ; n: RoomNumber ; begin for n := 0 to pred(rooms) do area[n] := 0 ; for r := 1 to M do for c := 1 to N do inc(area[Map[r, c].nr]) ; maxarea := 0 ; for n := 0 to pred(rooms) do if area[n] > maxarea then maxarea := area[n] end { MeasureRooms } ; var bestrow: Row ; bestcol: Column ; bestdir: Direction ; procedure BestWall ; var r: Row ; c: Column ; maxp: integer ; procedure Update(k1, k2: RoomNumber; d: Direction) ; var p: integer ; begin if k1 = k2 then p := area[k1] else p := area[k1] + area[k2] ; if p > maxp then begin maxp := p ; bestrow := r ; bestcol := c ; bestdir := d end { if } end { Update } ; begin maxp := 0 ; for r := 1 to M do for c := 1 to N do with Map[r, c] do begin if (r <> M) and wall[south] then Update(nr, Map[r+1, c].nr, south) ; if (c <> N) and wall[east] then Update(nr, Map[r, c+1].nr, east) ; end { for c with Map } end { BestWall } ; procedure ComputeAnswer ; begin PaintMap ; if Test then WriteColors ; MeasureRooms ; BestWall end { ComputeAnswer } ; procedure WriteOutput ; begin if Test then begin writeln('Number of rooms = ', rooms:1) ; writeln('Maximum room area = ', maxarea:1) ; writeln('Best wall to remove = ', bestrow:1, ' ', bestcol:1, ' ', bestdir:1) end { if Test } ; writeln(out, rooms:1) ; writeln(out, maxarea:1) ; write(out, bestrow:1, ' ', bestcol:1, ' ') ; case bestdir of south: writeln(out, 'S') ; east: writeln(out, 'E') ; end { case } end { WriteOutput } ; begin Init ; ReadInput ; if Test then WriteCastle ; ComputeAnswer ; WriteOutput ; Fini end.