【问题标题】:Backtracking prorblem and I don't know if my plan to solve it is correct回溯问题,我不知道我的解决方案是否正确
【发布时间】:2021-01-22 20:34:19
【问题描述】:

我正在练习回溯问题,这是问题描述: https://practiceit.cs.washington.edu/problem/view/cs2/sections/recursivebacktracking/travel

编写一个 travel 方法,它接受整数 x 和 y 作为参数,并使用递归回溯打印通过重复使用三个移动之一在二维平面中从 (0, 0) 到 (x, y) 移动的所有解:

东(E):向右移动1(增加x) 北(N):向上移动1(增加y) 东北(NE):向上移动 1 和向右移动 1(增加 x 和 y)。

这是我得到的: 我让它在一条路径上工作,但我不确定如何让它去探索所有其他可能的路径。我认为我的基本案例设计是错误的,但我不确定。我只想知道我应该首先解决什么问题,是基本情况还是我的整个概念是错误的。

public class PracticeRecordCode {
    public static void main(String[] args) {
        travel(1, 2);
    }
    public static String travel(int x, int y){
        List<String> allpath = new ArrayList<String>();

        String eachpath = "";

        return explore(0, 0, x, y, eachpath, allpath);
    }

    public static String explore(int x, int y, int des_x, int dest_y, String eachPath, List<String> allpath) {
        //Base case
        if(x == des_x && y== dest_y) {
                String result = "";
                if(isRepeated(eachPath, allpath)){
                    allpath.add(eachPath);
                    eachPath = "";
                }
            // Print all content from allpath
                for (String path : allpath) {
                    result += path + "\n";
                    System.out.println(path);
                }
                return result;
        } else {

            if(x == des_x && y != dest_y){
                eachPath += "N ";
                if(!allpath.contains(eachPath)) {
                    allpath.add(eachPath);
                }
                explore(x, y+1, des_x, dest_y, eachPath, allpath);
            } else if(x != des_x && y == dest_y) {
                eachPath += "E ";
                allpath.add(eachPath);
                explore(x + 1, y, des_x, dest_y, eachPath, allpath);
            } else {
                eachPath += "NE ";
                allpath.add(eachPath);
                explore(x + 1, y+1, des_x, dest_y, eachPath, allpath);
            }
        }
        return "";
    }

    // Check if this path has been done already
    public static boolean isRepeated(String path, List<String> allpath){
        return allpath.contains(path);
    }

}

【问题讨论】:

    标签: java recursive-backtracking


    【解决方案1】:

    我们可以对您的explore 方法进行一些改进,因为您的实现存在一些缺陷。退出条件有两种: 1. 当您到达目的地时,这是一条有效路径,我们可以将其保存到您的最终结果中。 2.您到达目的地(x&gt;des_x || y&gt;dest_y),这意味着这是一条无效路径,我们不必再继续探索了。否则,您有 3 个选项可以继续探索:E、N 或 NE。由于每个方向都是独一无二的,您不必担心重复。 完成所有可能的探索后,您的 allpath 列表将添加所有有效路径。您可以返回列表或打印它。 基于此,您的代码可以像这样简单得多:

    import java.util.ArrayList;
    import java.util.List;
    
    public class PracticeRecordCode {
    
        public static void main(String[] args) {
            travel(2, 2);
        }
        public static void travel(int x, int y){
            List<String> allpath = new ArrayList<String>();
    
            explore(0, 0, x, y, "", allpath);
    
            // Print all content from allpath
            for (String path : allpath) {
                System.out.println(path);
            }
    
        }
    
        public static void explore(int x, int y, int des_x, int dest_y, String eachPath, List<String> allpath) {
            //Base case
            if(x == des_x && y == dest_y) {
                allpath.add(eachPath);
                return;
            }
            if(x>des_x || y>dest_y)
                return;
            explore(x + 1, y, des_x, dest_y, eachPath + "E ", allpath);
    
            explore(x, y+1, des_x, dest_y, eachPath + "N ", allpath);
    
            explore(x + 1, y+1, des_x, dest_y, eachPath + "NE ", allpath);
        }
    }
    

    【讨论】:

    • 谢谢,我认为最让我困惑的是我将所有探索递归都放在 if-else 语句中的部分,并且我没有在每次递归期间更改我的 eachPath,因此它不会自行更新。
    • 加上我确实搞砸了基本情况,应该至少有两个条件。我认为这是我之前无法理解的主要原因。
    • 是的,您的 if-else 语句逻辑不正确:if(x == des_x && y != dest_y),这意味着它仅在 x == des_x 时移动 'E'ast,但实际上,它可以在 x 时移动
    【解决方案2】:

    你可以试试我的代码。希望它能给你的解决方案->

    public static void main(String[] args) {
        baktracking(new boolean[5][3], 0, 0, 2, 2, "");
    }
    
    static void baktracking(boolean m[][], int x, int y, int dx, int dy, String ans) {
        if (x == dx && y == dy) {
            System.out.println(ans);
            return;
        }
        if (x < 0 || y < 0 || x >= m.length || y >= m[0].length) {
            return;
        }
        m[x][y] = true;
        baktracking(m, x, y +1, dx, dy, ans + "E" + " ");
        baktracking(m, x + 1, y, dx, dy, ans + "N" + " ");
        baktracking(m, x + 1, y + 1, dx, dy, ans + "NE" + " ");
        m[x][y] = false;
    }
    

    【讨论】:

    • 我认为如果我知道如何改进它会更好,但我很欣赏代码,我可以从中得到一些想法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    相关资源
    最近更新 更多