题目: | 母亲的牛奶 | |
来源: | Usaco1.4.4 | |
题目大意: | 有三个容量分别是A,B,C升的桶,最初,A和B桶都是空的,而C桶是装满牛奶的。有时,农民 把牛奶从一个桶倒到 另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全 的。由于节约, 牛奶不会有丢失。写一个程序去帮助农民找出当A桶是空的时候,C桶中牛奶 所剩量的所有可能性。 | |
数据范围: | A,B,C分别是三个从1到20的整数 | |
样例: |
8 9 10 |
1 2 8 9 10 |
做题思路: | 刚开始迷茫的打算用人脑加dfs,然后无辜的挂了,人脑解见大牛代码。 然后有规规矩矩的dfs了,只要弄清灌水方法,dfs很好写(无非是a→b,a→c等) | |
知识点: | dfs、模拟、数学方法、记忆化 |
//纯dfs
{
ID:Dount Nameless
TASK:milk3
LANG:PASCAL
}
var
ans:array[0..21]of boolean;
f:array[0..21,0..21,0..21]of boolean;
a,b,c,i,j:longint;
procedure dfs(x,y,z:longint);
begin
if(x<0)or(y<0)or(z<0) then exit;{<超出实际>}
if(x>a)or(y>b)or(z>c) then exit;{<超出实际>}
iff[x,y,z] then exit;{<该状态存在过>}
f[x,y,z]:=true;
ifx=0 then ans[z]:=true;{<记录答案>}
dfs(0,x+y,z);dfs(x-b+y,b,z);{<a→b>}
dfs(0,y,x+z);dfs(x-c+z,y,c);{<a→c>}
dfs(x+y,0,z);dfs(a,y-a+x,z);{<b→a>}
dfs(x,0,z+y);dfs(x,y-c+z,c);{<b→c>}
dfs(x+z,y,0);dfs(a,y,z-a+x);{<c→a>}
dfs(x,y+z,0);dfs(x,b,z-b+y);{<c→b>}
end;
begin
assign(input,'milk3.in');reset(input);
assign(output,'milk3.out');rewrite(output);
readln(a,b,c);
fillchar(ans,sizeof(ans),false);
fillchar(f,sizeof(f),false);
dfs(0,0,c);
fori:=0 to c-1 do
ifans[i] then write(i,' ');
writeln(c);
close(input);close(output);
end.
//人脑解法,没的解释,不懂的地方自己笔算(就是不停地a灌b,b灌c,c灌a 这类的)
{
ID:Dount Nameless
TASK:milk3
LANG:PASCAL
}
var i,o:text;
a,b,c,t,d,e:integer;
list:array [1..50] of boolean;
begin
assign (i,'milk3.in');
assign(o,'milk3.out');
reset(i);
rewrite(o);
readln(i,a,b,c);
for t:=1 to 50 do
list[t]:=false;
ifa >c then a:=c;
ifb >c then b:=c;
ifa<=b
then for t:=0 to 20 do
begin
d:=c+a*t;
while d>=c do d:=d-b;
list[d]:=true;
if (d<b) and (c-d<a) then break;
end
else for t:=0 to 20 do
begin
d:=c-b*t;
while d>=b do
begin
d:=d-b;
if c-d>a then
begin
d:=d+a;
list[d]:=true;
end;
end;
end;
list[c-b]:=true;
for t:=0 to 20 do
begin
d:=c-a*t;
while d<c-b do d:=d+b;
list[d]:=true;
if (d<a) and (c-d<b) then break;
end;
for t:=0 to c-1 do
if list[t]=true then write(o,t,' ');
writeln(o,c);
close(o);
end.
题目来源:
http://ace.delos.com/usacoprob2?a=YqYGTaSaabV&S=milk3