Отримання знань

дистанційна підтримка освіти школярів


Клуб гурманов
http://acm.pku.edu.cn/JudgeOnline/problem?id=1058

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

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

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

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

   Анализ условия и обсуждение идеи решения

   Пример решения на Pascal:

var sat      : array ['A'..'P','A'..'P'] of boolean;
cansit : array ['A'..'P',1..6] of char;
bound : array ['A'..'P'] of boolean;
mates : array ['A'..'P',1..3] of integer;
solution : array [1..5,1..4,1..4] of char;

type string3 = string[3];
procedure InitMat;
var c,r : char;
begin
for r := 'A' to 'P' do
for c := 'A' to 'P' do
sat[r,c] := (r = c);
end;

procedure ReadData;
var
line,partners : string;
night,table : integer;
i,j,n : integer;
begin

for night := 1 to 3 do begin
Readln(line);
n := 1;
for table := 1 to 4 do begin
while not (line[n] in ['A'..'P']) do inc(n);
partners := Copy(line,n,4);
for i := 1 to 3 do begin
for j := i+1 to 4 do begin
sat[partners[i],partners[j]] := True;
sat[partners[j],partners[i]] := True;
end;
end;
for i := 1 to 4 do
solution[night,table,i] := partners[i];
n := n + 4;
end;
end;

end;

procedure FindAllowedSeating;
var c,r : char;
i : integer;
begin
for r := 'A' to 'P' do begin
i := 1;
for c := 'A' to 'P' do begin
if not sat[r,c] then begin
cansit[r,i] := c;
inc(i);
end;
end;
end;
end;

function FindFinalSeating(c : char): string3;
var i : integer;
s : string;
begin
s := '';
for i := 1 to 6 do
if (i <> mates[c,1]) and (i <> mates[c,2]) and (i <> mates[c,3]) then
s := s + cansit[c,i];
FindFinalSeating := s;
end;

function FindSolution: boolean;
var c,d : char;
ok : boolean; { whether we have a valid configuration }
i : integer;
s3,d3 : string3; { s3 is c's mates on evening 5, d3 is d's mates on same }
found : boolean;

function SetNextCfg(c : char): boolean;
var ans : boolean;
begin
ans := True;
if mates[c,3] = 6 then begin
if mates[c,2] = 5 then begin
if mates[c,1] = 4 then
ans := False
else begin
inc(mates[c,1]);
mates[c,2] := mates[c,1] + 1;
mates[c,3] := mates[c,2] + 1;
end
end
else begin
inc(mates[c,2]);
mates[c,3] := mates[c,2] + 1;
end;
end
else
inc(mates[c,3]);
SetNextCfg := ans;
end;

{ AssignTableMates updates all necessary data structures when c allocates }
{ three of his allowed mates to sit with him on the fourth evening. }
procedure AssignTableMates(c : char);
var i : integer;
begin
{ Assign tablemates seats with c }
bound[cansit[c,mates[c,1]]] := True;
bound[cansit[c,mates[c,2]]] := True;
bound[cansit[c,mates[c,3]]] := True;
{ Update the sat array with new seating }
for i := 1 to 3 do begin
sat[c,cansit[c,mates[c,i]]] := True;
sat[cansit[c,mates[c,i]],c] := True;
end;
sat[cansit[c,mates[c,1]],cansit[c,mates[c,2]]] := True;
sat[cansit[c,mates[c,1]],cansit[c,mates[c,3]]] := True;
sat[cansit[c,mates[c,2]],cansit[c,mates[c,3]]] := True;
sat[cansit[c,mates[c,2]],cansit[c,mates[c,1]]] := True;
sat[cansit[c,mates[c,3]],cansit[c,mates[c,1]]] := True;
sat[cansit[c,mates[c,3]],cansit[c,mates[c,2]]] := True;
end;

{ DeassignTableMates does the reverse of AssignTableMates. It is used when }
{ we have to backtrack. }
procedure DeassignTableMates(c : char);
var i : integer;
begin
{ Deassign tablemates seats with c }
bound[cansit[c,mates[c,1]]] := False;
bound[cansit[c,mates[c,2]]] := False;
bound[cansit[c,mates[c,3]]] := False;
{ Update the sat array with new seating }
for i := 1 to 3 do begin
sat[c,cansit[c,mates[c,i]]] := False;
sat[cansit[c,mates[c,i]],c] := False;
end;
sat[cansit[c,mates[c,1]],cansit[c,mates[c,2]]] := False;
sat[cansit[c,mates[c,1]],cansit[c,mates[c,3]]] := False;
sat[cansit[c,mates[c,2]],cansit[c,mates[c,3]]] := False;
sat[cansit[c,mates[c,2]],cansit[c,mates[c,1]]] := False;
sat[cansit[c,mates[c,3]],cansit[c,mates[c,1]]] := False;
sat[cansit[c,mates[c,3]],cansit[c,mates[c,2]]] := False;
end;

procedure Backtrack;
begin
while (c >= 'A') and not ok do begin
repeat
dec(c);
until (not bound[c]);
{ Unassign c's mates and find him others }
DeassignTableMates(c);
ok := SetNextCfg(c);
end;
end;

procedure MoveToNextMember;
var i : integer;
begin
inc(c);
if not bound[c] then
for i := 1 to 3 do mates[c,i] := i; { Initialize tablemate pick for c }
end;

begin
for c := 'A' to 'P' do bound[c] := False; { init who is assigned a seat }
c := 'A'; { begin at first member }
ok := True; { we are ok at the start }
for i := 1 to 3 do mates['A',i] := i; { Initialize tablemate pick for 'A' }
{ main loop }
while ok and (c < 'Q') and (c >= 'A') do begin { if we find a solution then c will go over 'P' }
{ if no solution then SetNextCfg will return False }
if not bound[c] then begin
{ Find tablemates for c: }
{ 1. Pick different tablemates while one of c's mates is bound or }
{ two of his mates have already sat next to one another. }
{ Note: We try to eliminate as many illegal possibilities as we }
{ can here, to save time; hence the complex condition. }
while ok and
(bound[cansit[c,mates[c,1]]] or
bound[cansit[c,mates[c,2]]] or
bound[cansit[c,mates[c,3]]] or
sat[cansit[c,mates[c,1]],cansit[c,mates[c,2]]] or
sat[cansit[c,mates[c,1]],cansit[c,mates[c,3]]] or
sat[cansit[c,mates[c,2]],cansit[c,mates[c,3]]]) do
ok := SetNextCfg(c);
{ 2. If ok then we have found tablemates for c; }
{ else c can't sit anywhere, so we have to backtrack }
if ok then begin
AssignTableMates(c);
{ Make sure the fifth evening is OK }
s3 := FindFinalSeating(c);
ok := not (sat[c,s3[1]] or sat[c,s3[2]] or sat[c,s3[3]]);
{ Move on or backtrack according to whether fifth evening is ok. }
{ Note that if c='A' here we have backtracked as far as we can. }
if ok then
MoveToNextMember
else if c > 'A' then begin
Backtrack;
ok := True;
end
else begin
FindSolution := False;
ok := False;
exit;
end;
end
else if c > 'A' then begin
Backtrack;
ok := True;
end
else begin
FindSolution := False;
ok := False;
exit;
end;
end
else begin
d := 'A';
found := False; { I.e. haven't found d }
while not found and (d < c) do begin
if not bound[d] then begin
d3 := FindFinalSeating(d);
if pos(c,d3) > 0 then found := True; { c sits with d on fifth }
end;
inc(d);
end;
if found then begin
dec(d);
for i := 1 to 3 do
if (c <> d3[i]) and sat[c,d3[i]] then
ok := False;
end;
if ok then
MoveToNextMember
else begin
Backtrack;
ok := True;
end;
end;
end;
FindSolution := ok;
end;

procedure WriteSolution;
var c : char;
table : integer;
last : string3;
i : integer;
done : array ['A'..'P'] of boolean; { Needed to see who's already seated }
{ on the fifth evening }
begin
table := 1;
for c := 'A' to 'P' do begin
if not bound[c] then begin
solution[4,table,1] := c;
solution[4,table,2] := cansit[c,mates[c,1]];
solution[4,table,3] := cansit[c,mates[c,2]];
solution[4,table,4] := cansit[c,mates[c,3]];
inc(table);
end;
end;
for c := 'A' to 'P' do done[c] := False;
table := 1;
for c := 'A' to 'P' do begin
if not done[c] then begin
{ Then c isn't assigned a seat on the fifth night - find him one }
if not bound[c] then
{ Then we can use the FindFinalSeating function }
last := FindFinalSeating(c)
else begin
{ Then the mates vector isn't defined for c: Can't use the }
{ FindFinalSeating function => We have to check whether c has }
{ sat with each member of his cansit vector. }
last := '';
for i := 1 to 6 do
if not sat[c,cansit[c,i]] then last := last + cansit[c,i];
end;
solution[5,table,1] := c;
solution[5,table,2] := last[1];
solution[5,table,3] := last[2];
solution[5,table,4] := last[3];
done[last[1]] := True;
done[last[2]] := True;
done[last[3]] := True;
inc(table);
end;
end;
end;



procedure SolveIt;
var s : string;
n,t,i : integer;
begin
if FindSolution then begin
WriteSolution;
for n := 1 to 5 do begin
s := '';
for t := 1 to 4 do begin
for i := 1 to 4 do s := s + solution[n,t,i];
s := s + ' ';
end;
Writeln(s);
end;
end
else
Writeln('It is not possible to complete this schedule.');
end;

begin
while not Eof do
begin
InitMat;
ReadData;
FindAllowedSeating;
SolveIt;
if not Eof then Readln;
writeln;
end;
end.
Попередня Зміст Наступна
В системі: гості - (); користувачі - (0)