Задание:
У нас есть 3 чашки с максимальными объемами A,B,C. Объемы находящейся в чашках жидкости X,Y,Z.
Мы можем выливать воду из чашки и наливать ее в другие. Вода в чашку наливается до заполнения (т.е. до максимального объема), остаток остается в чашке. Воду нельзя никуда больше выливать.
Нужно определить все объемы которые мы можем получить в результате переливаний.
Вывести в виде 0:1 1:2 2:3.
Первая цифра объем, вторая минимальное количество переливаний.
Язык: pascal
Решение задачи состоит в переборе всех возможных состояний чашек. Т.е. необходимо использовать алгоритм поиска в ширину.
Алгоритм
- Заносим в список начальное состояние
- пока в списке что-то есть
- берем первый попавшийся элемент списка
- добавляем в список все возможные состояния чашек получаемые из текущего, кроме тех что уже были добавлены ранее
- удаляем текущий элемент из списка
Максимальный объем | ||||
Начальный объем | ||||
program pereliv;
var a,b,c,x,y,z:integer;
olist:array[0..10] of integer;
i:integer;
type
pL = ^tL;
tL = record
x,y,z:integer;
id:longint;
step:integer;
next:pL;
end;
var
list,dlist:pL;
function inList(list:pL;id:longint):boolean;
var ls:pL;
begin
ls:=list;
inList:=false;
if ls = nil then exit;
while ls^.next
nil do begin
if ls^.id = id then begin inList:=true; exit;end;
ls:=ls^.next;
end;
end;
procedure addp(l:pL);
var t:pL;
begin
l^.next:=nil;
if dlist = nil then begin dlist:=l; exit;end;
t:=dlist;
while t^.next
nil do t:=t^.next;
t^.next:=l;
end;
procedure del(var lst:pL);
var l:pL;
begin
l:=lst^.next;
addp(lst);
lst:=l;
end;
procedure delm(var l:pL);
var n:pL;
begin
while l
nil do begin
n:=l^.next;
dispose(l);
l:=n;
end;
end;
procedure addv(v,c:integer);
begin
if olist[v] > c then olist[v]:=c;
end;
procedure add(var l:pL;x,y,z,s:integer);
var cc,ll:pL;
id:longint;
begin
if (x < 0) or (y < 0) or (z < 0) or (x > a) or (y > b) or (z > c) then exit;
id:= longint(x) + (longint(y) shl 8) + (longint(z) shl 16);
ll:=l;
if ll <> nil then begin
if inList(list, id) or inList(dlist,id) then
exit;
while ll^.next <> nil do ll:=ll^.next;
new(ll^.next);cc:=ll^.next;
end else begin new(list);ll:=list;cc:=ll;end;
cc^.x:=x;
cc^.y:=y;
cc^.z:=z;
addv(x,s);
addv(y,s);
addv(z,s);
cc^.step:=s;
cc^.id:=id;
cc^.next:=nil;
end;
procedure add_moves(l:pL);
var x,y,z:integer;
begin
if l <> nil then begin
if a-l^.x < l^.y then begin x:=a; y:=l^.y - (a-l^.x);z:=l^.z;end else begin x:= l^.x+l^.y; y:=0; z:=l^.z;end;
add(list,x,y,z,l^.step+1);
if a-l^.x < l^.z then begin x:=a; z:=l^.z - (a-l^.x);y:=l^.y;end else begin x:= l^.x+l^.z; z:=0; y:=l^.y;end;
add(list,x,y,z,l^.step+1);
if b-l^.y < l^.x then begin y:=b; x:=l^.x - (b-l^.y);z:=l^.z;end else begin y:= l^.y+l^.x; x:=0; z:=l^.z;end;
add(list,x,y,z,l^.step+1);
if b-l^.y < l^.z then begin y:=b; z:=l^.z - (b-l^.y);x:=l^.x;end else begin y:= l^.y+l^.z; z:=0; x:=l^.x;end;
add(list,x,y,z,l^.step+1);
if c-l^.z < l^.x then begin z:=c; x:=l^.x - (c-l^.z);y:=l^.y;end else begin z:= l^.z+l^.x; x:=0; y:=l^.y;end;
add(list,x,y,z,l^.step+1);
if c-l^.z < l^.y then begin z:=c; y:=l^.y - (c-l^.z);x:=l^.x;end else begin z:= l^.z+l^.y; y:=0; x:=l^.x;end;
add(list,x,y,z,l^.step+1);
end;
end;
begin
for i:=0 to 10 do olist[i]:=11;
list:=nil;
dlist:=nil;
readln(a,b,c,x,y,z); //4 1 1 1 1 1
//a:=4;b:=1;c:=1;
//x:=1;y:=1;z:=1;
add(list,x,y,z,0);
while list <> nil do begin
add_moves(list);
del(list);
end;
for i:=0 to 10 do begin
if olist[i] <> 11 then write(i,':',olist[i],' ')
end;
delm(dlist);
end.
Реализация на JavaScript:
var olist=[],
list=[],
dlist=[],
xx,yy,zz,a,b,c,tid;
var did=document.getElementById('out');
function inList(el, idx, arr) {
if(tid == el.id) return true;
return false;
}
function add(x,y,z,s){
if ((x < 0)||(y < 0)||(z < 0) || (x > a) || (y > b) || (z > c)) return;
tid=x+(y<<8)+(z<<16);
if(list.some(inList) || dlist.some(inList)) return;
if (olist[x] > s) olist[x]=s;
if (olist[y] > s) olist[y]=s;
if (olist[z] > s) olist[z]=s;
list.push({x:x,y:y,z:z,s:s,id:tid});
}
function pereliv(){
for(var i=0;i<11;i++) olist[i]=11;
a=4;b=1;c=1;
xx=1;yy=1;zz=1;
add(xx,yy,zz,0);
while(list.length >0){
p=list.shift();
// did.innerHTML+= p.x+','+p.y+','+p.z+','+p.id+'
';
if (a-p.x < p.y) {tx=a; ty=p.y - (a-p.x);tz=p.z;} else {tx= p.x+p.y; ty=0; tz=p.z;}
add(tx,ty,tz,p.s+1);
if (a-p.x < p.z) {tx=a; tz=p.z - (a-p.x);ty=p.y;} else {tx= p.x+p.z; tz=0; ty=p.y;}
add(tx,ty,tz,p.s+1);
if (b-p.y < p.x) {ty=b; tx=p.x - (b-p.y);tz=p.z;} else {ty= p.y+p.x; tx=0; tz=p.z;}
add(tx,ty,tz,p.s+1);
if (b-p.y < p.z) {ty=b; tz=p.z - (b-p.y);tx=p.x;} else {ty= p.y+p.z; tz=0; tx=p.x;}
add(tx,ty,tz,p.s+1);
if (c-p.z < p.x) {tz=c; tx=p.x - (c-p.z);ty=p.y;} else {tz= p.z+p.x; tx=0; ty=p.y;}
add(tx,ty,tz,p.s+1);
if (c-p.z < p.y) {tz=c; ty=p.y - (c-p.z);tx=p.x;} else {tz= p.z+p.y; ty=0; tx=p.x;}
add(tx,ty,tz,p.s+1);
dlist.push(p);
}
did.innerHTML='';
for(i=0;i<11;i++)if(olist[i]!=11) did.innerHTML+=i+':'+olist[i]+'
';
}