递归问题解决倒水问题

问题

三个水杯A、B、C容量分别为11L、5L、6L,现A中有10L,B中有1L水,每次必须倒水方倒完或者被倒水方加满,最终A中装8L水。

思路

可以用递归方法解决此问题。
(1)每次倒水方式有6种可能,分别是A->B、A->C、B->A、B->C、C->A、C->B。
(2)记录每次倒完水A、B、C种的水量,每次记录都不相同。
(3)若有重复记录,则此次操作失败,尝试下一种倒水方式。
(4)若6种都失败,删除上次倒水记录,回归到上一次倒水的下一种倒水方式。
(5)依次类推,直到倒出A种8L水,层层返回成功。

实现(golang版)

package main

import (
    "fmt"
)

var CUP1 = cup{10, 11}
var CUP2 = cup{1, 5}
var CUP3 = cup{0, 6}

type cup struct {
    lv  int // 水位
    cap int // 容积
}

func (c *cup) level() int {
    return c.lv
}

func (c *cup) capacity() int {
    return c.cap
}

func (c *cup) validate() bool {
    return c.lv <= c.cap
}

func (from *cup) pour(to *cup) bool {
    if from.lv < 0 || to.lv < 0 {
        panic("water level error")
    }

    // from有水,并且to没满
    if from.lv != 0 && to.lv != to.cap { // 10, 5
        // to可以倒满
        if toLeft := to.cap - to.lv; toLeft < from.lv {
            to.lv = to.cap
            from.lv -= toLeft
        } else { // to不能倒满
            to.lv += from.lv
            from.lv = 0
        }
        return true
    }
    return false
}

func (c *cup) String() string {
    return fmt.Sprintf("lv: %2d, cap: %2d\n", c.lv, c.cap)
}

type PourWater struct {
    cup1    cup
    cup2    cup
    cup3    cup
    history [][3]cup
}

// 最终要求,一号杯装8升水
func (p *PourWater) last() bool {
    return p.cup1.level() == 8
}

func (p *PourWater) pour() bool {
    if !p.cup1.validate() || !p.cup2.validate() || !p.cup3.validate() {
        panic("cup error: lv > cap")
    }

    // 判断该当前步骤是否重复
    current := [3]cup{p.cup1, p.cup2, p.cup3}
    for _, v := range p.history {
        if v == current {
            return false
        }
    }

    // 将当前步骤放入历史操作队列中
    p.history = append(p.history, current)
    //fmt.Println(p)
    if p.last() {
        return true
    }

    // cup1 -> cup2
    a, b, c := p.cup1, p.cup2, p.cup3
    if p.cup1.pour(&p.cup2) && p.pour() {
        return true
    }

    // cup1 -> cup3
    p.cup1, p.cup2, p.cup3 = a, b, c
    if p.cup1.pour(&p.cup3) && p.pour() {
        return true
    }

    // cup2 -> cup1
    p.cup1, p.cup2, p.cup3 = a, b, c
    if p.cup2.pour(&p.cup1) && p.pour() {
        return true
    }

    // cup2 -> cup3
    p.cup1, p.cup2, p.cup3 = a, b, c
    if p.cup2.pour(&p.cup3) && p.pour() {
        return true
    }

    // cup3 -> cup1
    p.cup1, p.cup2, p.cup3 = a, b, c
    if p.cup3.pour(&p.cup1) && p.pour() {
        return true
    }

    // cup3 -> cup2
    p.cup1, p.cup2, p.cup3 = a, b, c
    if p.cup3.pour(&p.cup2) && p.pour() {
        return true
    }

    // 6种步骤都不成功,退回上一步操作(类似悔棋)
    p.history = p.history[:len(p.history)-1]
    //fmt.Println(p)
    return false
}

func (p *PourWater) String() string {
    var s string
    for i := 0; i < len(p.history); i++ {
        s += fmt.Sprintf("%d,%d,%d -> ", p.history[i][0].level(), p.history[i][1].level(), p.history[i][2].level())
    }
    return s
}

func main() {
    pw := &PourWater{CUP1, CUP2, CUP3, make([][3]cup, 0)}
    pw.pour()
    fmt.Println(pw)
}

结果:10,1,0 -> 6,5,0 -> 6,0,5 -> 1,5,5 -> 1,4,6 -> 7,4,0 -> 7,0,4 -> 2,5,4 -> 2,3,6 -> 8,3,0 ->

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