1.4.4 Mother's Mil 母亲的牛奶

欢迎访问https://blog.csdn.net/lxt_Lucia~~

宇宙第一小仙女\(^o^)/~~萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗~~

 

 

Description

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

 

Input

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

 

Output

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

 

Sample Input

8 9 10

Sample Output

1 2 8 9 10

 

思路一:

最开始的时候想简单了,后来细想发现一共有6种方式,12种情况。

1)6种方式分别为:

A->B,B->A;

A->C,C->A;

B->C,C->B;

2)12种情况是因为:

每种方式都有两种可能,如第一种情况A->B(把A桶往B桶里倒),依题仅有两种情况停止:

要么把A倒空,要么B被倒满。其他方式也是如此,所以一共有12种情况。

把这6种方式,12种情况想清楚了就很好做了,设二维数组logo[a][b]来标记该A,B桶里剩余量的情况是否出现过,若出现过则无需再继续下去,另设数组s存所有C桶可能出现的牛奶量。

 

代码一:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define fori(a,b) for(int i=a;i<=b;i++)
#define forj(a,b) for(int j=a;j<=b;j++)
#define mem(a,b) memset(a,b,sizeof(a))

using namespace std;

int va,vb,vc,k=0,logo[21][21],s[1000000];

void dfs(int a,int b,int c)
{
    if(logo[a][b]!=-1)
        return ;
    logo[a][b]=1;
    if(a==0)
        s[k++]=c;
    if(a-(vb-b)>0)
        dfs(a-(vb-b),vb,c);
    else
        dfs(0,b+a,c);
    if(b-(va-a)>0)
        dfs(va,b-(va-a),c);
    else
        dfs(a+b,0,c);
    if(a-(vc-c)>0)
        dfs(a-(vc-c),b,vc);
    else
        dfs(0,b,c+a);
    if(c-(va-a)>0)
        dfs(va,b,c-(va-a));
    else
        dfs(a+c,b,0);
    if(b-(vc-c)>0)
        dfs(a,b-(vc-c),vc);
    else
        dfs(a,0,c+b);
    if(c-(vb-b)>0)
        dfs(a,vb,c-(vb-b));
    else
        dfs(a,b+c,0);
}

int main()
{
    int a,b,c;
    fori(0,20)
        forj(0,20)
            logo[i][j]=-1;
    scanf("%d%d%d",&va,&vb,&vc);
    a=0;b=0;c=vc;
    dfs(a,b,c);
    sort(s,s+k);
    fori(0,k-1)
    {
        if(i==0)
            printf("%d",s[i]);
        else
            printf(" %d",s[i]);
    }
    return 0;
}

 

思路二:

与第一种思路大致相同,区别就在于用map进行了优化,同时二维数组logo[a][b]的值不再是仅仅标记此情况是否出现过,它的值表示的是A,B桶量固定时,此时C桶的牛奶量。

 

代码二:

#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long LL;
#define fori(a) for(LL i=0;i<a;i++)
#define forj(a) for(LL j=0;j<a;j++)
#define mem(a,b) memset(a,b,sizeof(a))

using namespace std;


int a,b,c;
map<int,int>m;
int logo[30][30];

void init()
{
    fori(30)
        forj(30)
            logo[i][j]=-1;
}

void DFS(int x,int y,int z)
{
    if(logo[x][y]!=-1)
        return;
    else
        logo[x][y]=z;
    DFS(x-min(x,c-z),y,z+min(x,c-z));
    DFS(x,y-min(y,c-z),z+min(y,c-z));
    DFS(x+min(y,a-x),y-min(y,a-x),z);
    DFS(x-min(x,b-y),y+min(x,b-y),z);
    DFS(x+min(z,a-x),y,z-min(z,a-x));
    DFS(x,y+min(z,b-y),z-min(z,b-y));
}

int main()
{
    init();
    cin>>a>>b>>c;
    DFS(0,0,c);
    int flag=0;
    for(int i=29;i>=0;i--)
        if(logo[0][i]!=-1)
            if(flag==0)
                cout<<logo[0][i],flag++;
            else
                cout<<" "<<logo[0][i],flag++;
        cout<<endl;
    return 0;
}

 

 

 

宇宙第一小仙女\(^o^)/~~萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗~~

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值