算法之倒水的问题

需求:现在只有两只杯子,容量分别是:5升和7升,问题是:在只用这两个杯子的前提下,如何才能得到4升水?假设:水可以无限使用。

fun water(volume1 : Int, volume2: Int, volume: Int){
    println("得到两个杯子:${volume1}L,${volume2}L,目标为${volume}L")
    var x = 0
    var cup1 = 0
    var cup2 = 0
    loop@ while (x != volume){
        println("给 cup1 装满水")
        println("cup1 向 cup2 倒水")
        cup1 = volume1
        while (cup2 + cup1 >= volume2){
            cup1 -= (volume2 - cup2)
            cup2 = 0
            x = cup1
            if(x == volume){
                break@loop
            }
            println("cup2 水满倒掉")
            println("cup1 把剩下 $x 倒入 cup2")
        }
        if (cup2 + cup1 < volume2){
            cup2 += cup1
            cup1 = 0
            x = cup1
        }
        println("cup1 水量 $cup1 cup2 水量 $cup2")
    }
    println("cup1 得到 ${x}L 水")
}

fun main(){
    water(5, 7, 4)
}

输出结果

得到两个杯子:5L,7L,目标为4L
给 cup1 装满水
cup1 向 cup2 倒水
cup1 水量 0 cup2 水量 5
给 cup1 装满水
cup1 向 cup2 倒水
cup2 水满倒掉
cup1 把剩下 3 倒入 cup2
cup1 水量 0 cup2 水量 3
给 cup1 装满水
cup1 向 cup2 倒水
cup2 水满倒掉
cup1 把剩下 1 倒入 cup2
cup1 水量 0 cup2 水量 1
给 cup1 装满水
cup1 向 cup2 倒水
cup1 水量 0 cup2 水量 6
给 cup1 装满水
cup1 向 cup2 倒水
cup1 得到 4L 水

如果将上面的杯子调换一下

fun main(){
    water(7, 5, 4)
}

输出结果

得到两个杯子:7L,5L,目标为4L
给 cup1 装满水
cup1 向 cup2 倒水
cup2 水满倒掉
cup1 把剩下 2 倒入 cup2
cup1 水量 0 cup2 水量 2
给 cup1 装满水
cup1 向 cup2 倒水
cup1 得到 4L 水

算法看似行的通,但是还存在以下几点缺陷:

  1. 无法判断方案是否行的通,如果得不到对应的水的话,会无限循环下去
  2. 这里只有cup1能得到对应水,没有判断cup2得到相应水的情况。例如,是water(2, 5, 4)的情况下,就会无限循环,但是第二轮的时候cup2已经得到了4L水。
    针对以上问题,对算法做改进:记录每次cup1和cup2的水量,如果出现重复,则不会得到结果;对cup2的水量也进行判断。
    改进后的算法如下:
fun water(volume1 : Int, volume2: Int, volume: Int){
    println("得到两个杯子:${volume1}L,${volume2}L,目标为${volume}L")

    var record = mutableListOf<String>()
    var cup1 = 0
    var cup2 = 0

    loop@ while (cup1 != volume && cup2 != volume){
        if (record.contains("$cup1-$cup2")){
            println("得不到结果")
            break@loop
        }else{
            record.add("$cup1-$cup2")
        }
        println("给 cup1($cup1) 装满水")
        cup1 = volume1
        println("cup1($cup1) 向 cup2($cup2) 倒水")
        while (cup2 + cup1 >= volume2){
            cup1 -= (volume2 - cup2)
            cup2 = 0
            if(cup1 == volume){
                break@loop
            }
            println("cup2($cup2) 水满倒掉")
            if (cup1 == 0){
                continue@loop
            }
            println("把cup1($cup1) 剩下 $cup1 倒入 cup2($cup2)")
        }
        if (cup2 + cup1 < volume2){
            cup2 += cup1
            cup1 = 0
            if (cup2 == volume){
                break@loop
            }
        }
        println("cup1 水量 $cup1 cup2 水量 $cup2")
    }
    println("cup1 得到 ${cup1}L 水")
    println("cup2 得到 ${cup2}L 水")
    println(record)
}

以上算法,去掉了多余的中间变量X,同时将while内部的那个while用求余的方式表示,精简了代码

仔细考查,算法还存在一些不完美的地方。大致说几个问题:

  1. 比如给出2个1L的杯子,得到2L的水。这个算法会输入:不会得到结果。但是2个1L的杯子,不就是2L水嘛。
  2. 比如给出2个1L的杯子,得到1L的水。这个算法会先向cup1倒水,然后再倒入cup2,然后cup2倒掉,又回到0L和0L的两个杯子,给出得不到结果。但是1L的cup1就直接能得到结果。

希望有更好的算法能与大家交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352