每天写一点代码----倒水问题(庞果网)

问题描述:

有两个容器,容积分别为A升和B升,有无限多的水,现在需要C升水。

我们还有一个足够大的水缸,足够容纳C升水。起初它是空的,我们只能往水缸里倒入水,而不能倒出。

可以进行的操作是:

1,把一个容器灌满; 

2,把一个容器清空(容器里剩余的水全部倒掉,或者倒入水缸);

3,用一个容器的水倒入另外一个容器,直到倒出水的容器空或者倒入水的容器满。     

问是否能够通过有限次操作,使得水缸最后恰好有C升水。

 输入:三个整数A, B, C,其中 0 < A , B, C <= 1000000000

 输出:true或false,表示能否达到要求。


算法描述:

这是一个标准的倒水问题,各大公司的面试题上面出现了很多版本了。如果看过算法的书,这是一个扩展的欧几里得算法。

就是看 A*x+B*y=M这个方程有没有x,y的整数解的问题,代码非常简单,基本上照搬扩展欧几里得算法就可以了。

不明白的可以看看欧几里得算法,说得很明白了。简单的说,就是有这么一条定律:


定理:

对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。

如果求出最大公约数以后,再用C对这个公约数取模,如果为0表示满足要求,否则就不行。

 

简单的说,就是通过辗转相除得到一个公约数,而这个公约数是a和b互相倒水可以倒出来的,再看这个公约数是不是c的约数。

比如3和5,辗转相除以后,最大公约数是1,这个1是这么倒水倒出来的。

a倒入b,装满a再倒入b,这时a中就是1了。

再看1是不是c的约数,如果是,那就能倒1,倒1,倒1。。。一直倒满c了。

再比如4和6,辗转相除以后是2,这样,如果c是一个奇数,就到不满了。。不行你自己可以试试,加入c是7,你怎么倒都倒不了了。。

(以上来自:http://www.cnblogs.com/dyllove98/archive/2013/07/24/3212578.html


Java实现:

 /**
     * 求最大公约数
     * 
     * @param a
     * @param b
     * @return
     */
    private static int gcd(int a, int b) {
        int temp;
        if (a < b) {/* 交换两个数,使大数放在a上 */
            temp = a;
            a = b;
            b = temp;
        }
        while (b != 0) {/* 利用辗除法,直到b为0为止 */
            temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }

    public static boolean can(int a, int b, int c) {
        int gcd = gcd(a, b);
        if (c % gcd == 0) {
            return true;
        }
        return false;
    }



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值