【問題描述】
有兩個無刻度標誌的水壺,分別可裝x公升和y公升 ( x,y 為整數且均不大於100)的水。設另有一水缸,可用來向水壺灌水或接從水壺中倒出的水, 兩水壺間,水也可以相互傾倒。已知x公升壺為空壺, y公升壺為空壺。問如何通過倒水或灌水操作, 用最少步數能在x或y公升的壺中量出 z(z ≤ 100)公升的水來。
3 22 1 14
看到求最少步數,馬上想到用廣度優先搜尋,那麼問題在於如何展開?要不要剪枝?其實,這道題是不需要任何剪枝的,只要判重就行了,那麼關鍵就在於如何展開。
對於x壺和y壺,設它們壺中各裝了a,b公升水,那麼一共有以下六種操作:
若a>0且b0時可以反操作。
若a>0時,可將x向水缸中倒出a公升水,此時x中沒有水,y中不變,若b>0時也可反操作。 若a
根據這六種操作,我們如何拓展的問題就解決了。
1uses math;
2type rec=record
3dep,x,y:longint;
4end;5
var a:array[1..1000] of
rec;
6 f:array[0..100,0..100] of
boolean;
7h,r,x,y,z,xx,yy:longint;
8begin
9readln(x,y,z);
10fillchar(f,sizeof(f),true);
11 f[0,0]:=false;
12 h:=0;r:=1;13
while h<>r do
14begin
15inc(h);
16if (a[h].x>=0)and(a[h].y<=y) then
17begin
18inc(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);
21if
not(f[a[r].x,a[r].y]) then
22dec(r)
23else
24 f[a[r].x,a[r].y]:=false;
25end;26
if (a[r].x=z)or(a[r].y=z) then
27begin
28writeln(a[r].dep);
29exit;
30end;31
if (a[h].x<=x)and(a[h].y>=0) then
32begin
33inc(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);
36if
not(f[a[r].x,a[r].y]) then
37dec(r)
38else
39 f[a[r].x,a[r].y]:=false;
40end;41
if (a[r].x=z)or(a[r].y=z) then
42begin
43writeln(a[r].dep);
44exit;
45end;46
if a[h].x>=0
then
47begin
48inc(r);
49 a[r]:=a[h];
50 a[r].dep:=a[h].dep+1;a[r].x:=0;51
ifnot(f[a[r].x,a[r].y]) then
52dec(r)
53else
54 f[a[r].x,a[r].y]:=false;
55end;56
if (a[r].x=z)or(a[r].y=z) then
57begin
58writeln(a[r].dep);
59exit;
60end;61
if a[h].x<=x then
62begin
63inc(r);
64 a[r]:=a[h];
65 a[r].dep:=a[h].dep+1;a[r].x:=x;
66if
not(f[a[r].x,a[r].y]) then
67dec(r)
68else
69 f[a[r].x,a[r].y]:=false;
70end;71
if (a[r].x=z)or(a[r].y=z) then
72begin
73writeln(a[r].dep);
74exit;
75end;76
if a[h].y>=0
then
77begin
78inc(r);
79 a[r]:=a[h];
80 a[r].dep:=a[h].dep+1;a[r].y:=0;81
ifnot(f[a[r].x,a[r].y]) then
82dec(r)
83else
84 f[a[r].x,a[r].y]:=false;
85end;86
if (a[r].x=z)or(a[r].y=z) then
87begin
88writeln(a[r].dep);
89exit;
90end;91
if a[h].y<=y then
92begin
93inc(r);
94 a[r]:=a[h];
95 a[r].dep:=a[h].dep+1;a[r].y:=y;
96if
not(f[a[r].x,a[r].y]) then
97dec(r)
98else
99 f[a[r].x,a[r].y]:=false;
100end
;101
if (a[r].x=z)or(a[r].y=z) then
102begin
103writeln(a[r].dep);
104exit;
105end
;106
end;//六種展開方式,每次展開後都要判重,然後看是否達到目標
107 writeln('
impossible');
108end.
CodeVS1226 倒水問題
題目描述 description 有兩個無刻度標誌的水壺,分別可裝 x 公升和 y 公升 x,y 為整數且均不大於 100 的水。設另有一水 缸,可用來向水壺灌水或接從水壺中倒出的水,兩水壺間,水也可以相互傾倒。已知 x 公升壺為空 壺,y 公升壺為空壺。問如何通過倒水或灌水操作,用最少步數能在x或...
倒水問題 (codevs 1226) 題解
有兩個無刻度標誌的水壺,分別可裝x公升和y公升 x,y 為整數且均不大於100 的水。設另有一水缸,可用來向水壺灌水或接從水壺中倒出的水,兩水壺間,水也可以相互傾倒。已知x公升壺為空壺,y公升壺為空壺。問如何通過倒水或灌水操作,用最少步數能在x或y公升的壺中量出 z z 100 公升的水來。3 22...
CODEVS 倒水問題
題目描述 有兩個無刻度標誌的水壺,分別可裝 x 公升和 y 公升 x,y 為整數且均不大於 100 的水。設另有一水 缸,可用來向水壺灌水或接從水壺中倒出的水,兩水壺間,水也可以相互傾倒。已知 x 公升壺為空 壺,y 公升壺為空壺。問如何通過倒水或灌水操作,用最少步數能在x或y公升的壺中量出 z z...