三水桶平分8升水(javascript完成)

此为《算法的兴趣》读书笔记,我用javascript从新完成算法。

题目形貌

有三个容器分别是三升、五升和八升的水桶,个中容积为八升的水桶装满了水,其他两桶为空。水桶没有刻度,除这三个桶外不能运用别的容器,将8升水等分为两份4升的水。

解题思绪

以三水桶盛水量为一个矢量状况,倒水能够推进状况的转变,如许会构成一个状况树,我们采纳深度优先搜刮体式格局举行穷举。
书中运用用了C++规范库的双端行列,还用了构造体,并将桶状况封装成了类,比较难看懂,我发现用javascript举行合理的设想,代码简朴易懂^_^。

变量定义

桶的最大容量及状况变化行列

var FullBacket = [8,5,3]            //桶的最大容量
var states = [[8,0,0]];             //状况行列,js的数组已已有行列和客栈的支撑

检测倒水操纵是不是可行

限定前提为:桶的序号0~2;倒出水的桶不能为空;倒入水的桶不能是满的。

function CanTakeDumpAction(curr,from,to){
    if(from >= 0 && from < 3 && to >= 0 && to < 3){
        if(from != to && curr[from] > 0 && curr[to] < FullBacket[to]){
            return true;
        }
    }
    return false;
}

倒水操纵

倒水量的盘算要注重两个方面,一是目的桶的盈余容积;二是源桶的盈余水量,二者取小。

function DumpWater(curr,from,to){
    var next = curr.slice();        //js对象为援用传值,这里要复制一份
    var dump_water = FullBacket[to] - curr[to] > curr[from] ? curr[from] : FullBacket[to] - curr[to]            //倒水量的盘算
    next[from] -= dump_water;
    next[to] += dump_water;
    return next;
}

检测新状况是不是已涌现过

这个函数是保证不会进入死循环,注重:foreach半途不能退出,此处不能用它。

function IsStateExist(state){
    for(var i = 0; i < states.length; i++){
        if(state[0] == states[i][0] && state[1] == states[i][1] && state[2] == states[i][2]){
            return true;
        }
    }
    return false;
}

状况搜刮主函数

边界前提有两个,一为找到了准确解,一为一切状况都检测完,并未找到准确解。

(function SearchState(states){
    var curr = states[states.length - 1];
    if(curr[0] == 4 && curr[1] == 4){            //找到准确解
        var rs = ''
        states.forEach(function(al){
            rs += al.join(',') + ' -> ';
        });
        console.log(rs.substr(0,rs.length - 4))
    }

    for(var j = 0; j < 3; j++){                //一切的倒水计划即为桶编号的全分列
        for(var i = 0; i < 3; i++){
            if(CanTakeDumpAction(curr,i,j)){
                var next = DumpWater(curr,i,j);
                if(!IsStateExist(next)){        //找到新状况
                    states.push(next);
                    SearchState(states);
                    states.pop();
                }
            }
        }
    }
})(states);

16组准确解

8,0,0 -> 3,5,0 -> 0,5,3 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 4,4,0
8,0,0 -> 3,5,0 -> 3,2,3 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 4,4,0
8,0,0 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 0,5,3 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 4,4,0
8,0,0 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 4,4,0
8,0,0 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 4,4,0
8,0,0 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 0,5,3 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 4,4,0
8,0,0 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 4,4,0
8,0,0 -> 3,5,0 -> 3,2,3 -> 0,5,3 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 4,4,0
8,0,0 -> 5,0,3 -> 0,5,3 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 4,4,0
8,0,0 -> 5,0,3 -> 5,3,0 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 4,4,0
8,0,0 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 0,5,3 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 4,4,0
8,0,0 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 4,4,0
8,0,0 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 0,5,3 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 4,4,0
8,0,0 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 7,0,1 -> 7,1,0 -> 4,1,3 -> 4,4,0
8,0,0 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 4,4,0
8,0,0 -> 5,0,3 -> 5,3,0 -> 2,3,3 -> 2,5,1 -> 0,5,3 -> 3,5,0 -> 3,2,3 -> 6,2,0 -> 6,0,2 -> 1,5,2 -> 1,4,3 -> 4,4,0
    原文作者:zhoutk
    原文地址: https://segmentfault.com/a/1190000004907496
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞