Usaco 1.4.4 母亲的牛奶(Mother's Milk)

14 篇文章 0 订阅

题目:

 母亲的牛奶

来源:

 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值