有两个无刻度标志的水壶,分别可装x升和y升 ( x,y 为整数且均不大于100)的水。设另有一水缸,可用来向水壶灌水或接从水壶中倒出的水, 两水壶间,水也可以相互倾倒。已知x升壶为空壶, y升壶为空壶。问如何通过倒水或灌水操作, 用最少步数能在x或y升的壶中量出 z(z ≤ 100)升的水来。
3 22 1
14
看到求最少步数,马上想到用广度优先搜索,那么问题在于如何展开?要不要剪枝?其实,这道题是不需要任何剪枝的,只要判重就行了,那么关键就在于如何展开。
对于x壶和y壶,设它们壶中各装了a,b升水,那么一共有以下六种操作:
若a>0且b<y,那么可以用x向y中倾倒min(a,y-b)升水,此时,x中剩余a-min(a,y-b)升水,y中剩余b+min(a,y-b)升水,同理,当a<x,b>0时可以反操作。
若a>0时,可将x向水缸中倒出a升水,此时x中没有水,y中不变,若b>0时也可反操作。
若a<x时,可从水缸中倒出x-a升水至x中,此时x中有x升水,y中不变,b<y时也可反操作。
根据这六种操作,我们如何拓展的问题就解决了。
1 uses math; 2 type rec=record 3 dep,x,y:longint; 4 end; 5 var a:array[1..1000] of rec; 6 f:array[0..100,0..100] of boolean; 7 h,r,x,y,z,xx,yy:longint; 8 begin 9 readln(x,y,z); 10 fillchar(f,sizeof(f),true); 11 f[0,0]:=false; 12 h:=0;r:=1; 13 while h<>r do 14 begin 15 inc(h); 16 if (a[h].x>=0)and(a[h].y<=y) then 17 begin 18 inc(r); 19 a[r]:=a[h]; 20 a[r].dep:=a[h].dep+1;a[r].x:=a[h].x-min(a[h].x,y-a[h].y);a[r].y:=a[h].y+min(a[h].x,y-a[h].y); 21 if not(f[a[r].x,a[r].y]) then 22 dec(r) 23 else 24 f[a[r].x,a[r].y]:=false; 25 end; 26 if (a[r].x=z)or(a[r].y=z) then 27 begin 28 writeln(a[r].dep); 29 exit; 30 end; 31 if (a[h].x<=x)and(a[h].y>=0) then 32 begin 33 inc(r); 34 a[r]:=a[h]; 35 a[r].dep:=a[h].dep+1;a[r].x:=a[h].x+min(a[h].y,x-a[h].x);a[r].y:=a[h].y-min(a[h].y,x-a[h].x); 36 if not(f[a[r].x,a[r].y]) then 37 dec(r) 38 else 39 f[a[r].x,a[r].y]:=false; 40 end; 41 if (a[r].x=z)or(a[r].y=z) then 42 begin 43 writeln(a[r].dep); 44 exit; 45 end; 46 if a[h].x>=0 then 47 begin 48 inc(r); 49 a[r]:=a[h]; 50 a[r].dep:=a[h].dep+1;a[r].x:=0; 51 if not(f[a[r].x,a[r].y]) then 52 dec(r) 53 else 54 f[a[r].x,a[r].y]:=false; 55 end; 56 if (a[r].x=z)or(a[r].y=z) then 57 begin 58 writeln(a[r].dep); 59 exit; 60 end; 61 if a[h].x<=x then 62 begin 63 inc(r); 64 a[r]:=a[h]; 65 a[r].dep:=a[h].dep+1;a[r].x:=x; 66 if not(f[a[r].x,a[r].y]) then 67 dec(r) 68 else 69 f[a[r].x,a[r].y]:=false; 70 end; 71 if (a[r].x=z)or(a[r].y=z) then 72 begin 73 writeln(a[r].dep); 74 exit; 75 end; 76 if a[h].y>=0 then 77 begin 78 inc(r); 79 a[r]:=a[h]; 80 a[r].dep:=a[h].dep+1;a[r].y:=0; 81 if not(f[a[r].x,a[r].y]) then 82 dec(r) 83 else 84 f[a[r].x,a[r].y]:=false; 85 end; 86 if (a[r].x=z)or(a[r].y=z) then 87 begin 88 writeln(a[r].dep); 89 exit; 90 end; 91 if a[h].y<=y then 92 begin 93 inc(r); 94 a[r]:=a[h]; 95 a[r].dep:=a[h].dep+1;a[r].y:=y; 96 if not(f[a[r].x,a[r].y]) then 97 dec(r) 98 else 99 f[a[r].x,a[r].y]:=false; 100 end; 101 if (a[r].x=z)or(a[r].y=z) then 102 begin 103 writeln(a[r].dep); 104 exit; 105 end; 106 end;//六种展开方式,每次展开后都要判重,然后看是否达到目标 107 writeln('impossible'); 108 end.