[USACO 1.4.4] Mother's Milk

[题目描述]

Mother's Milk

母亲的牛奶

农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,最初,A和B桶都是空的,而C桶是装满牛奶的。有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。
写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。

PROGRAM NAME: milk3

INPUT FORMAT

单独的一行包括三个整数A,B和C。

SAMPLE INPUT (file milk3.in)

8 9 10

OUTPUT FORMAT

只有一行,列出当A桶是空的时候,C桶牛奶所剩量的所有可能性。

SAMPLE OUTPUT (file milk3.out)

1 2 8 9 10

SAMPLE INPUT (file milk3.in)

2 5 10

SAMPLE OUTPUT (file milk3.out)

5 6 7 8 9 10


[解题思路]

简单的记忆化搜索。

记f[a,b,c]为三个桶当前的状态,true则为可以到此状态,false则不行,枚举6种倒牛奶的情况,最后看f[0,c[3]-i,i]是否可达(c[3]为c桶的容量),是就输出i。


[Code]

{
ID: zane2951
PROG: milk3
LANG: PASCAL
}

program milk3;
var
   c:array[0..4] of longint;
   ans:array[0..21] of longint;
   f:array[0..21,0..21,0..21] of boolean;
   i,top:longint;

//-----------min-----------
function min(a,b:longint):longint;
begin
   if a<b then exit(a) else exit(b);
end;

//-----------run-----------
procedure run(x,y,z:longint);
var
   xx,yy,zz:longint;

begin
   if f[x,y,z] then exit;
   f[x,y,z]:=true;
   if x>0 then
      begin
         //-------x to y---------
         yy:=min(c[2],y+x);
         xx:=x-(yy-y);
         run(xx,yy,z);
         //-------x to z---------
         zz:=min(c[3],z+x);
         xx:=x-(zz-z);
         run(xx,y,zz);
      end;
   if y>0 then
      begin
         //-------y to x---------
         xx:=min(c[1],x+y);
         yy:=y-(xx-x);
         run(xx,yy,z);
         //-------y to z---------
         zz:=min(c[3],z+y);
         yy:=y-(zz-z);
         run(x,yy,zz);
      end;
   if z>0 then
      begin
         //-------z to x---------
         xx:=min(c[1],x+z);
         zz:=z-(xx-x);
         run(xx,y,zz);
         //-------z to y---------
         yy:=min(c[2],y+z);
         zz:=z-(yy-y);
         run(x,yy,zz);
      end;
end;

//----------main-----------
begin
   assign(input,'milk3.in'); reset(input);
   assign(output,'milk3.out'); rewrite(output);
   readln(c[1],c[2],c[3]);
   run(0,0,c[3]); top:=0;
   for i:=0 to c[3] do
      if f[0,c[3]-i,i] then begin inc(top); ans[top]:=i; end;
   for i:=1 to top-1 do write(ans[i],'':1);
   writeln(ans[top]);
   close(input); close(output);
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值