重新拾起递归

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<c&&c>0)

fac(A,b,c-(A-a));

if(B-b>=c&&c>0)

fac(a,b+c,0);

else if(B-b<c&&c>0)

fac(a,B,c-(B-b));

if(B-b>a&&a>0)

fac(0,b+a,c);

else if(B-b<a&&a>0)

fac(a-(B-b),B,c);

if(C-c>a&&a>0)

fac(0,b,c+a);

else if(C-c<a&&a>0)

fac(a-(C-c),b,C);

if(A-a>b&&b>0)

fac(a+b,0,c);

else if(A-a<b&&b>0)

fac(A,b-(A-a),c);

if(C-c>b&&b>0)

fac(a,0,c+b);

else if(C-c<b&&b>0)

fac(a,b-(C-c),C);

return;

#include<iostream>
using 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<<i<<' ';
    return 0;
}
View Code

 

}

最终将bool n数组里面的true的下标都输入就可以了。

speech.gif posted on 2018-03-14 09:15 kgxpbqbyt 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值