SalesPath-计算最便宜的路径

时间:2019-01-06 21:42:25

标签: recursion tree

我有一棵树(代表一个SalesPath),每个节点都有成本。

对象用于计算最小的SalesPath,即每个节点的成本之和 从根节点到叶节点

下面的代码使用递归来解决问题,代码工作正常 (在显示的树中,SalesPath(0-3-2-1-1)的最便宜路径= 7)

我在查看堆栈时遇到困难,无法清楚地说明/解释递归如何跟踪最便宜的成本 (即int最便宜= cheapestCost + rootNode.cost)在多个分支之间

例如从0-5-4,最便宜的费用是9 而从0-3 -2 -1 -1,最便宜的费用是7

任何人都可以对此提供简单的解释吗? h

代码:

 static class SalesPathRecursion{

            static int getCheapestCost_Recursion(Node rootNode){

                int cheapestCost = Integer.MAX_VALUE;
                Node[] children = rootNode.children;

                int tempCost =0;

                if(children == null){
                    System.out.println(" Children == null, returning rootNode.cost => " + rootNode.cost);
                    return rootNode.cost;
                }else{
                    for(int i=0; i< children.length; i++){
                        tempCost = getCheapestCost_Recursion(children[i]);

                        if(tempCost < cheapestCost){
                            cheapestCost = tempCost;
                        }
                        System.out.println(" CheapestCost is " + cheapestCost);
                    }
                }

                int cheapest = cheapestCost + rootNode.cost;
                System.out.println(" Returning : rootNode.cost => " + rootNode.cost + " cheapest is => " + cheapest);

                return cheapest;
            }
        }

1 个答案:

答案 0 :(得分:0)

这是递归的经典示例!

调用方调用递归函数,传入根节点并询问“叶子的最便宜的价格是多少?”。调用树底部的根节点(0)响应:“我不确定。请稍等,让我的每个孩子看看哪个孩子的成本最低”。但是,还没有一个孩子对这个问题有任何答案,因此他们向每个孩子询问完全相同的问题,依此类推。

最终,到达leaf node(例如,您的示例中为4),并说:“我知道!从我到叶节点的最便宜的费用是我自己的价值,4我要告诉父母。”这称为base case。基本情况是迄今为止的第一个函数调用,它提供了一个非常小的子问题的明确答案,在此情况下,该信息将用于构建更大问题的解决方案。将太大而无法立即解决的问题分解为容易解决的小问题的过程称为divide and conquer

节点4的父节点5现在知道从其自身到叶子(4,它的唯一子节点)的最便宜的成本是5 + 4 = 9,并告诉其父节点根节点0。根节点是现在,它从其最左边的子级获得了确定的值(从根到叶的路径成本为9,比无穷大,因此它是迄今为止存储的最好的),但仍然需要询问其他子项的成本,是的。最终,所有孩子都会报告各自的费用,其中0->3->2->1->1证明是最便宜的。

该算法使用depth-first search,先探索一个分支,然后再探索其他任何分支。换句话说,0->5->40->3->2->1->1之前已被完全研究。


示例1

考虑一个具有独特成本的小型示例树:

        0
       / \
      4   1
     /  
    5  

我们希望0->1是成本为1的最便宜的路径。让我们在该树上使用详细的会话输出来运行该算法。每当进行递归调用时,打印都会缩进。括号是指特定的节点。查看是否可以跟踪执行情况:

(0), what's your min cost?
(0) says: Hang on, I need to ask my children...
(0) says: I'm asking (4) for its min cost...
      (4), what's your min cost?
      (4) says: Hang on, I need to ask my children...
      (4) says: I'm asking (5) for its min cost...
            (5), what's your min cost?
            (5) says: I'm a leaf! My min cost is 5
      (4) says: I got the cost 5 from (5), a new best!
      (4) says: I checked my children and I know my min cost is 9
(0) says: I got the cost 9 from (4), a new best!
(0) says: I'm asking (1) for its min cost...
      (1), what's your min cost?
      (1) says: I'm a leaf! My min cost is 1
(0) says: I got the cost 1 from (1), a new best!
(0) says: I checked my children and I know my min cost is 1

示例2

这是另一棵更大的树,再次具有唯一的节点:

         0
       / | \
      4  1  7
     /  / \  
    5  6   2
            \
             3

我们希望0->1->2->3是成本为6的最便宜的路径。让我们看一下详细的输出。再试一次以跟踪执行情况。

(0), what's your min cost?
(0) says: Hang on, I need to ask my children...
(0) says: I'm asking (4) for its min cost...
      (4), what's your min cost?
      (4) says: Hang on, I need to ask my children...
      (4) says: I'm asking (5) for its min cost...
            (5), what's your min cost?
            (5) says: I'm a leaf! My min cost is 5
      (4) says: I got the cost 5 from (5), a new best!
      (4) says: I checked my children and I know my min cost is 9
(0) says: I got the cost 9 from (4), a new best!
(0) says: I'm asking (1) for its min cost...
      (1), what's your min cost?
      (1) says: Hang on, I need to ask my children...
      (1) says: I'm asking (6) for its min cost...
            (6), what's your min cost?
            (6) says: I'm a leaf! My min cost is 6
      (1) says: I got the cost 6 from (6), a new best!
      (1) says: I'm asking (2) for its min cost...
            (2), what's your min cost?
            (2) says: Hang on, I need to ask my children...
            (2) says: I'm asking (3) for its min cost...
                  (3), what's your min cost?
                  (3) says: I'm a leaf! My min cost is 3
            (2) says: I got the cost 3 from (3), a new best!
            (2) says: I checked my children and I know my min cost is 5
      (1) says: I got the cost 5 from (2), a new best!
      (1) says: I checked my children and I know my min cost is 6
(0) says: I got the cost 6 from (1), a new best!
(0) says: I'm asking (7) for its min cost...
      (7), what's your min cost?
      (7) says: I'm a leaf! My min cost is 7
(0) says: I got the cost 7 from (7) but it's not the best
(0) says: I checked my children and I know my min cost is 6

以下是产生以上输出的代码:

static void say(String message, int depth) {
    for (int i = 0; i < depth; i++) {
        System.out.print(" ");
    }

    System.out.println(message);
}

static int getCheapestCostRecursion(Node node, int depth) {
    say("(" + node.cost + "), what's your min cost?", depth);

    if (node.children.length == 0) {
        say(
            "(" + node.cost + 
            ") says: I'm a leaf! My min cost is " +
            node.cost, depth
        );
        return node.cost;
    }

    say(
        "(" + node.cost + 
        ") says: Hang on, I need to ask my children...",
        depth
    );

    int cheapestCost = Integer.MAX_VALUE;

    for (Node child : node.children) {
        say(
            "(" + node.cost + 
            ") says: I'm asking (" + child.cost + 
            ") for its min cost...", depth
        );

        int childCost = getCheapestCostRecursion(child, depth + 6);

        say(
            "(" + node.cost + 
            ") says: I got the cost " + childCost + 
            " from (" + child.cost + ")", depth
        );

        if (childCost < cheapestCost) {
            say(
                "(" + node.cost + 
                ") says: I got the cost " + childCost + 
                " from (" + child.cost + "), a new best",
                depth
            );
            cheapestCost = childCost;
        }
        else {
            say(
                "(" + node.cost + 
                ") says: I got the cost " + childCost + 
                " from (" + child.cost + 
                "), but it's not the best", depth
            );
        }
    }

    say(
        "(" + node.cost + 
        ") says: I checked my children and I know " +
        "my min cost is " + (cheapestCost + node.cost),
        depth
    );

    return cheapestCost + node.cost;
}

Try it!