(* Appiattisci (IOI 1999) Copyright (C) 2000 Paolo Boldi This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) program Ioi9922; {$R+} (* Siano v_1,...,v_p i valori iniziali delle pile; la soluzione, qualunque essa sia, comporter… un insieme di mosse relative alla pila 1, alla pila 2 ecc. Siano q_1,...,q_p i totali delle mosse relative alla pila 1,...,p, e sia N la media dei valori (cioŠ (v_1+...+v_p)/p). Allora: v_1-q_1+q_2=N v_i-2*q_i+q_(i-1)+q_(i+1)=N per i=2,...,p-1 v_p-q_p+q_(p-1)=N Questo sistema ha una sola soluzione, una volta fissato il valore di uno dei q_i. Inoltre, se (q_1,...,q_p) Š soluzione lo Š anche (q_1+a,...,q_p+a) per ogni a. La procedura solve calcola questo array (con una componente a 0). *) const DEBUG=false; maxp=200; nomefin='flat.inp'; nomefout='flat.out'; type stato=array [1..maxp] of longint; lista=^nodo; nodo=record (* Registra una mossa i->j *) i: byte; j: longint; next: lista end; var p: byte; (* Numero pile *) stin,q: stato; (* Input *) media: longint; (* Media input *) mcount: word; (* Numero di mosse *) primo,ultimo: lista; (* Primo/ultimo elemento della lista di mosse *) procedure inp; (* Legge l'input e lo mette in obiettivo. Pone in p il numero di pile, e in media la media *) var f: text; i: byte; tot: longint; begin assign(f,nomefin); reset(f); readln(f,p); tot:=0; for i:=1 to p do begin read(f,stin[i]); tot:=tot+stin[i] end; media:=tot div p; close(f) end; procedure solve; var i: byte; min: longint; begin q[1]:=0; (* Componente fissata *) q[2]:=media+q[1]-stin[1]; for i:=2 to p-2 do q[i+1]:=media+2*q[i]-q[i-1]-stin[i]; q[p]:=stin[p]+q[p-1]-media; (* Cerco minimo *) min:=0; for i:=2 to p do if (q[i]j *) begin if (i=1) then begin s[1]:=s[1]-j; s[2]:=s[2]+j end else if (i=p) then begin s[i]:=s[i]-j; s[i-1]:=s[i-1]+j end else begin s[i]:=s[i]-2*j; s[i-1]:=s[i-1]+j; s[i+1]:=s[i+1]+j end end; function finito: boolean; (* Guarda se stin Š costante e uguale a media *) var ok: boolean; i: byte; begin ok:=true; for i:=1 to p do begin ok:=(stin[i]=media); if (not ok) then break end; finito:=ok end; function fattibile(i: byte): longint; (* Da' il minimo fra q[i] e la mossa fattibile *) var s: longint; begin if (i=1) or (i=p) then s:=stin[i] else s:=stin[i] div 2; if (s>q[i]) then fattibile:=q[i] else fattibile:=s end; procedure outstato; (* SOLO PER DEBUG *) var i: byte; begin for i:=1 to p do write(stin[i],' '); writeln end; procedure risolvi; var imax,i: byte; j: longint; begin while (not finito) do begin (* Cerca i che massimizza il minimo fra la mossa fattibile e la mossa da fare *) imax:=1; for i:=2 to p do if (fattibile(i)>fattibile(imax)) then imax:=i; (* E' una mossa non nulla? *) if (fattibile(imax)>0) then begin j:=fattibile(imax); q[imax]:=q[imax]-j; muovi(stin,imax,j); if (DEBUG) then outstato; output(imax,j) end (* Altrimenti: incrementa ogni elemento di q del minimo non nullo di stin *) else begin if (DEBUG) then writeln('Costretto a incrementare q'); imax:=1; for i:=2 to p do if (stin[i]>0) and ((imax=1) or (stin[i]nil) do begin writeln(f,curs^.i,' ',curs^.j); curs:=curs^.next end; close(f) end; begin mcount:=0; inp; solve; risolvi; outputlista end.