T1
倒牛奶
农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,
最初,A和B桶都是空的,而C桶是装满牛奶的。有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。
写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。
输入格式 Input Format
单独的一行包括三个整数A,B和C。
输出格式 Output Format
只有一行,升序地列出当A桶是空的时候,C桶牛奶所剩量的所有可能性。
样例输入 Sample Input
SAMPLE INPUT 1
8 9 10
SAMPLE INPUT 2
2 5 10
样例输出 Sample Output
SAMPLE OUTPUT 1
1 2 8 9 10
SAMPLE OUTPUT 2
5 6 7 8 9 10
时间限制 Time Limitation
1s
注:
显而易见,这是一道递归题。首个状态是A、B桶是空的,C是满的。现在我们要求的是当A桶为空的时候,所有C桶的可能性。那么我们需要一个递归来完成这个倒牛奶的过程。然而,问题来了,当我们发现A桶为空的时候,怎么确定这时候的C的情况是否已经找到了呢?并且,递归结束的条件是什么呢?仔细一想,如果我们只考虑A空来结束递归,那第一重就会结束。可是这道题不像之前的,有什么边界限制。那么我们只能用一个bool型的数组来记录我们已经找过的情况,如果所有的情况找到了,那么就结束递归。因为是三个桶的状态,所以我们需要一个三维的数组。
伪代码:
void fac(int a,int b,int c)
{
if(f[a][b][c])
return ;
f[a][b][c]=1;
if(a==0)
n[c]=1;
if(A-a>=c&&c>0)
fac(a+c,b,0);
else if(A-a
fac(A,b,c-(A-a));
if(B-b>=c&&c>0)
fac(a,b+c,0);
else if(B-b
fac(a,B,c-(B-b));
if(B-b>a&&a>0)
fac(0,b+a,c);
else if(B-b0)
fac(a-(B-b),B,c);
if(C-c>a&&a>0)
fac(0,b,c+a);
else if(C-c0)
fac(a-(C-c),b,C);
if(A-a>b&&b>0)
fac(a+b,0,c);
else if(A-a0)
fac(A,b-(A-a),c);
if(C-c>b&&b>0)
fac(a,0,c+b);
else if(C-c0)
fac(a,b-(C-c),C);
return;
#includeusing namespace std; int A,B,C; int n[30]; bool f[30][30][30]; int x; bool a1=1,a2=1,a3=1,a4=1,a5=1,a6=1; void fac(int a,int b,int c) { if(f[a][b][c])return ; f[a][b][c]=true; if(a==0) { n[c]=1; } if(A-a>=c&&c>=0) fac(a+c,b,0); else if(c-(A-a)>=0&&c>=0) fac(A,b,c-(A-a)); if(B-b>=c&&c>=0) fac(a,b+c,0); else if(c-(B-b)>=0&&c>=0) fac(a,B,c-(B-b)); if(A-a>=b&&b>=0) fac(a+b,0,c); else if(b-(A-a)>=0&&b>=0) fac(A,b-(A-a),c); if(C-c>=b&&b>=0) fac(a,0,c+b); else if(b-(C-c)>=0&&b>=0) fac(a,b-(C-c),C); if(C-c>=a&&a>=0) fac(0,b,c+a); else if(a-(C-c)>=0&&a>=0) fac(a-(C-c),b,C); if(B-b>=a&&a>=0) fac(0,b+a,c); else if(a-(B-b)>=0&&a>=0) fac(a-(B-b),B,c); return ; } int main() { scanf("%d %d %d",&A,&B,&C); fac(0,0,C); for(int i=0;i<=29;i++) if(n[i]==1) cout<' '; return 0; }
}
最终将bool n数组里面的true的下标都输入就可以了。