【问题标题】:I am getting wrong answer for prime path problem can anyone help me in finding the issue?对于主要路径问题,我得到了错误的答案,任何人都可以帮助我找到问题吗?
【发布时间】:2020-02-23 14:13:37
【问题描述】:

问题链接:https://www.spoj.com/problems/PPATH/

问题的简要说明,

1) Construct a graph with prime numbers between 1000 and 9999.
2) Add an undirected edge between two numbers 'a' and 'b', if they differ only by one digit. 
EX: 1033 and 1733 differ only by one digit.
3) In that graph we need to find the length of the shortest path from the given source to the given destination.

我已经解决了上述问题,方法是使用 1000 到 9999 之间的质数,通过连接仅相差一位数的数字来构建图形。例如:1033 和 1733 仅相差一位。 我已经使用 DFS 和记忆来找到最短路径。 对于某些输入,我得到了错误的答案,比实际值大 1,因为有 1000 个节点我无法找出问题所在。如果有人帮助我解决问题,那将非常有帮助。

我知道这个问题可以通过 BFS 解决,但我需要知道这个问题有什么问题。

以下程序打印错误答案时的测试用例

1
7573 9973

实际答案:4
我的代码输出:5

(我通过提交 BFS 方法找到了实际答案,并在 SPOJ 中被接受)。

import java.util.*;
import java.lang.*;
import java.io.*;


class FireEscapeRoutes_FIRESC {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    public static void main(String[] args) throws Exception{
        int t = 1;
        while (t--!=0){
            int source = 7573;
            int destination = 9973;
            List<Integer> fourDigitPrimeNos = new ArrayList<>();

            for(int i=1001;i<=9999;i++){
                if(isPrime(i)){
                    fourDigitPrimeNos.add(i);
                    //System.out.println(i);
                }
            }
            Graph graph = new Graph(fourDigitPrimeNos.size());
            /*
             If two number 'a' and 'b' differ only by one digit then an edge is added.
             */
            for (int i=0;i<fourDigitPrimeNos.size();i++){
                for (int j=i+1;j<fourDigitPrimeNos.size();j++){
                    if(isSingleDistnace(fourDigitPrimeNos.get(i),fourDigitPrimeNos.get(j))){
                        graph.add(fourDigitPrimeNos.get(i),fourDigitPrimeNos.get(j));
                    }
                }
            }
            //System.out.println(graph.graph);
            Long minPath = graph.getShortestPath(source,destination);
            if(minPath!=Long.MAX_VALUE){
                System.out.println(minPath);
            }else{
                System.out.println("Impossible");
            }

        }
    }

    static boolean isSingleDistnace(int a, int b){
        String as = a+"";
        String bs = b+"";
        int ds = 0;
        for (int i=0;i<as.length();i++){
            if(!(as.charAt(i)==bs.charAt(i))){
                if(ds>=1){
                    return false;
                }
                ds++;
            }
        }
        if(ds==0){
            return false;
        }
        return true;
    }
    static boolean isPrime(int n){
        for (int i=2;i<=Math.sqrt(n);i++){
            if(n%i==0){
                return false;
            }
        }
        return true;
    }
}

class Graph{
    int noOfVertices;
    HashMap<Integer,List<Integer>> graph;
    Graph(int v){
        noOfVertices = v;
        graph = new HashMap<Integer,List<Integer>>();
    }
    void add(int u,int v){
        if (!graph.containsKey(u)){
            graph.put(u,new ArrayList<>());
        }
        if(!graph.containsKey(v)){
            graph.put(v,new ArrayList<>());
        }
        graph.get(u).add(v);
        graph.get(v).add(u);
    }

    Long getShortestPath(int start, int dest){
        HashMap<Integer,Long> visitedVsMinCost = new HashMap<>();
        Long min = Long.MAX_VALUE;
        min = getShortestPathUtil(start,dest,visitedVsMinCost);
        return min-1;


    }

    Long getShortestPathUtil(Integer start,Integer dest,HashMap<Integer,Long> visitedVsMinCost){

        if(start.equals(dest)){
            return 1l;
        }
        visitedVsMinCost.put(start, Long.MAX_VALUE);
        List<Integer> frnds = graph.get(start);
        Long min = Long.MAX_VALUE;
        for (Integer iThFrind:frnds){
            if(!visitedVsMinCost.containsKey(iThFrind)){
                Long shortestPathUtil = getShortestPathUtil(iThFrind, dest, visitedVsMinCost);
                //System.out.println(shortestPathUtil + " min " + min);
                min = Math.min(min, shortestPathUtil);

            }else {
                if(!visitedVsMinCost.get(iThFrind).equals(Long.MAX_VALUE)) {
                    min = Math.min(min, visitedVsMinCost.get(iThFrind)+1);
                }
            }
        }
        visitedVsMinCost.put(start,min);
        //System.out.println(min);
        if (min.equals(Long.MAX_VALUE)){
            return min;
        }
        return min+1;

    }
}

注意:下面的部分是为了解释为什么我的代码在@c0der 提到的情况下工作。由于我无法评论更多字符,我正在编辑这个问题。要了解方法,您可以使用以下部分。

我可以理解调试代码很困难,所以我尝试使用@coder 回答和提到的图表来解释我的方法 上面的代码在你提到的场景中工作正常。

起点 = 1,终点 = 5,最短路径 = 2 (1->4->5)

1) 如果 DFS 遍历 `1->2->3->4->5' 并到达目的地 '5' 它会将 '1' 返回到第 '4' 节点。

2) 现在第'4'节点记住返回值'1'。 (这意味着在4到5之间,有一个节点,包括目的地,不包括源4)。

2.1) 然后它返回'2'(1+1) 到'3'rd 节点。和'3'rd 节点记住值'2'。 (这意味着在第 3 个节点和目标(5)节点之间,有 2 个节点,在最短的路径中。包括目标,不包括源 3

3) 类似的调用将返回到“1”。

4) 然后是第'1'节点,调用第'4'节点并看到它之前被访问过,所以它取第'4'节点的记忆值'1'并将'2'返回到'1'。

【问题讨论】:

  • edit您的帖子澄清问题:1.“用单位距离连接数字”是什么意思? 2.“实际答案:4”请说明为什么是4 3.请对测试数据进行硬编码,使代码更容易测试。
  • @c0der 我已经编辑了问题,你能检查一下吗?
  • 谢谢。现在更清楚了。请说明原因实际答案:4
  • @c0der 我无法弄清楚为什么回答“4”,因为该图很大,有近 1000 个节点。我使用我在 SPOJ 中接受的 BFS 方法找到了实际答案。我已经编辑了我的问题来解释我的方法。请看一下。

标签: java graph depth-first-search breadth-first-search


【解决方案1】:

调试发布的代码是一项漫长的任务。
然而,DFS 并不是适合这项工作的工具。 为了形象化为什么 DFS 不是找到最短路径的好工具,请考虑以下简单图表:

如果 DSF 恰好开始遍历节点 1-&gt;2-&gt;3-&gt;4-&gt;5 最短路径 1-&gt;4-&gt;5
不会被遍历,因为4 被标记为已访问。
这可能是 DFS 和记忆法无法找到最短路径的原因。



编辑: 以下是您的代码的修改版本:它返回找到的实际最短路径(如果有)。
这可能有助于调试。
If 通过执行 DFS 遍历所有可能的路径并保持最短路径找到最短路径。
从某种意义上说,如果图中存在循环,它可能会重新计算之前已经计算过的路径,这并不是优化的。您可能希望添加计算路径的记忆功能以提高效率。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

class FireEscapeRoutes_FIRESC {

    public static void main(String[] args) throws Exception{

        List<Integer> fourDigitPrimeNos = new ArrayList<>();

        for(int i=1001; i<=9999; i++){
            if(isPrime(i)){
                fourDigitPrimeNos.add(i);
            }
        }

        Graph graph = new Graph();
        /*
             If two number 'a' and 'b' differ only by one digit then an edge is added.
         */
        for (int i=0;i<fourDigitPrimeNos.size();i++){
            for (int j=i+1;j<fourDigitPrimeNos.size();j++){
                if(isSingleDistnace(fourDigitPrimeNos.get(i),fourDigitPrimeNos.get(j))){
                    graph.add(fourDigitPrimeNos.get(i),fourDigitPrimeNos.get(j));
                }
            }
        }

        int source = 1033; 
        int destination = 8179;  //expected 6 : 1033  1733  3733  3739  3779  8779  8179

        /* more test cases
        int source = 7573;
        int destination = 9973; //expected 5

        int source = 1373;
        int destination = 8017; //expected 7

        int source = 1033;
        int destination = 1033; //expected 1
        */
        List<Integer> shortestPath = graph.getShortestPath(source,destination);

        if(shortestPath != null){
            System.out.println("\nPath Found :"+ shortestPath);
            System.out.println("Path length: "+shortestPath.size());
        }else{
            System.out.println("Impossible");
        }
    }

    static boolean isSingleDistnace(int a, int b){
        String as = a+"";
        String bs = b+"";
        int ds = 0;
        for (int i=0;i<as.length();i++){
            if(!(as.charAt(i)==bs.charAt(i))){
                if(ds>=1)
                    return false;
                ds++;
            }
        }
        if(ds==0)   return false;

        return true;
    }

    static boolean isPrime(int n){

        if (n <= 1) return false; //make sure it is positive

        for (int i=2;i<=Math.sqrt(n);i++){
            if(n%i==0)
                return false;
        }
        return true;
    }
}

class Graph{

    private final HashMap<Integer,List<Integer>> graph;
    //measure time and print out some progress indication
    private static long startTime, printime;
    private static long HEART_BEAT = 15000;

    Graph(){
        graph = new HashMap<>();
    }

    void add(int u,int v){
        if (!graph.containsKey(u)){
            graph.put(u,new ArrayList<>());
        }
        if(!graph.containsKey(v)){
            graph.put(v,new ArrayList<>());
        }
        graph.get(u).add(v);
        graph.get(v).add(u);
    }

    List<Integer> getShortestPath(int start, int dest){

        System.out.print("Working ");
        startTime = System.currentTimeMillis();

        List<Integer> path = new ArrayList<>();
        path = getShortestPathUtil(start,dest, Integer.MAX_VALUE, path);

        System.out.println("\n run time in minutes " + (double) (System.currentTimeMillis() - startTime) /60000);
        return path;
    }

    List<Integer> getShortestPathUtil(int start,int dest,int minLengthFound, List<Integer> path){

        if(System.currentTimeMillis() - printime >= HEART_BEAT ){
            System.out.print(".");
            printime = System.currentTimeMillis();
        }

        if(path.contains(start)) return null; //prevent loops

        path.add(start);
        if(start == dest) return path;
        //stop traverse if path is longer than the shortest one found earlier
        if(minLengthFound != Integer.MAX_VALUE && path.size() >= minLengthFound) return null;

        List <Integer> keepShortestPathFound = null;
        for (int neighbor : graph.get(start)){

            if(path.contains(neighbor)) {
                continue;
            }

            List<Integer> shortestPathFromNeighbor = getShortestPathUtil(neighbor, dest, minLengthFound, new ArrayList<>(path));
            if(shortestPathFromNeighbor != null && shortestPathFromNeighbor.contains(dest) &&
                    shortestPathFromNeighbor.size() < minLengthFound){
                keepShortestPathFound = shortestPathFromNeighbor;
                minLengthFound = shortestPathFromNeighbor.size();
            }
        }

        return keepShortestPathFound;
    }
}

【讨论】:

  • 我的代码适用于上述情况,因为我无法评论更多字符,我已经编辑了我的问题来解释我的方法。请查看我的问题的编辑部分。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-16
相关资源
最近更新 更多