广度优先搜索算法JAVA 8-puzzle

时间:2014-04-08 18:33:28

标签: java algorithm artificial-intelligence puzzle breadth-first-search

我试图为8益智游戏实现广度优先算法。我知道这不是一个新案例,而是网络上的一堆解决方案,但我想以我的思维方式来实现。

此代码已找到节点结果,即

123
456
780

但这需要350,000步才能完成!

任何想法都将不胜感激! =)

    //This method receives a Collection of `Nodo` objects, each one will be checked and compare with the finalGoal

     public void percorreNodos(Collection<Nodo> nodosBase)
            {
                //In this class a have an array that has all the IDs os nodes that already has been checked
                //The ID of a Node, is the representation: 123456780, 354126870 , etc..
                System.out.println("idsPercorrido.size() = " + idsPercorridos.size());
                //Check if the collection nodosBase contains the finalGoal
                Iterator<Nodo> iterator =  nodosBase.iterator();
                while( iterator.hasNext() )
                {
                    Nodo nodoBase = (Nodo) iterator.next();
                    //If this current node has already been checked, we dont have to check it again
                    idsPercorridos.add( nodoBase.getId() );
                            //Just print the node (sysout)
                    nodoBase.print();
                    contPassos++;
                    System.out.println( "\n" + contPassos + " STEPS(number of nodes checked)..." );
                    //Check if this node is the final goal
                    if( nodoBase.isObjetivoFinal() )
                    {
                                    //set the variable indicating that the result has been found
                        encontrouObjetivo = true;
                        System.out.println( "Resultado alcancado EM " + contPassos + " PASSOS..." );
                        nodoBase.print();
                        break;
                    }
                }

                // Now that we know that no one Node of nosoBase collection is the final goal, we are going to generate the next children to be checked, and call this function recursively 
                //Just confirm that we didnt find the goal 
                if(encontrouObjetivo == false)
                {
                            //Creates the next frontier
                    Collection<Nodo> novaFronteira = new HashSet<Nodo>();

                    for(Nodo nodoPai : nodosBase)
                    {
                                    //Generate each Node its childrens and add to a collection called "novaFronteira"
                        Collection<Nodo> filhos = nodoPai.gerarFilhos();
                        for(Nodo filho : filhos)
                        {
//idsPercorridos is a collection<String> which contains all the nodes ids that we checked, we dont want to check a node more than one time !
                            if( idsPercorridos.contains( filho.getId() ) == false )
                            {
                                novaFronteira.add( filho );

                            }
                        }
                    }
                    this.percorreNodos( novaFronteira );
                }

            }

2 个答案:

答案 0 :(得分:3)

您可以确保不向novaFronteira添加重复元素。

没有什么能阻止这段代码:

for(Nodo nodoPai : nodosBase)
{
    Collection<Nodo> filhos = nodoPai.gerarFilhos();
    for(Nodo filho : filhos)
    {
        if( idsPercorridos.contains( filho.getId() ) == false )
        {
            novaFronteira.add( filho );
        }
    }
}

从许多重复节点添加到novaFronteira

如果你要在if语句中添加idsPercorridos,那将阻止这种情况发生,并导致更少的步骤,但是,具体取决于你的数据和数据结构的样子,添加的运行这次通话的时间实际上可能比原来花费的时间更长。


如果问题是运行时间,则应确保idsPercorridosTreeSetHashSet,因为这些调用允许有效contains次呼叫,而不是ArrayList {1}}或LinkedList,但没有。{/ p>


如果这没有帮助,您可以尝试使用the A* algorithm,这涉及到每个节点添加一个启发式函数,这是到目标的距离 - 这允许我们探索更接近目标的节点首先,通常会减少到达那里的步骤。

良好的启发式函数可能是每个图块与其目标位置之间Manhattan distances的总和。

请注意,这会对您当前的代码进行相当多的更改。

答案 1 :(得分:0)

根据Wikipedia,此拼图有9!/2 = 181440种可能的可解组合。如果您检查每个节点中的每个组合(您不会这样做,但它会使计算更容易),则会执行大约(9!/2) * 9 = 1,632,960个步骤。因此,如果您的算法采用350,000步骤,我就不会发现问题,因为计算机可以快速执行 步骤。