当没有可用的解决方案时,在高峰时间求解器中进行宽度优先搜索循环

时间:2015-12-17 17:53:58

标签: java algorithm graph breadth-first-search

我正在尝试使用广度优先搜索来实现高峰时间求解算法,以遍历不同路径的图形,在找到解决方案时停止。

经过多次测试,我遇到了一个我不知道如何解决的问题。当有解决方案时,算法运行得很好,但是当找不到任何一个时,它只是无休止地循环,因为它重新创建包含与旧信息相同信息的“节点”,而不是如果信息是相同。当它发现没有更多的可能性时,我怎么能让它停下来?

以下是我为解算器使用的类:

这是我操作的主要类RushHour。 包rush.hour;

import java.io.*;
import java.util.List;
import java.util.ArrayList;

public class RushHour
{
    public static void main(String[] args) 
    {
        String fileName = "Parking.txt";
        String line;
        int lineNumber = 0;

        int numOfCars;
        List<Car> carsList = new ArrayList<>();

        try
        {
            FileReader fileReader = new FileReader(fileName);
            BufferedReader bufferedReader = new BufferedReader(fileReader);

            while((line = bufferedReader.readLine()) != null)
            {
                lineNumber += 1;
//                System.out.println(lineNumber);
                System.out.println(line);
                if (lineNumber == 15)
                    numOfCars = Integer.parseInt(
                            line.substring(line.length() - 1)) + 1;
                if (lineNumber >= 17)
                {
                    String[] splitLine = line.split(":");
                    char[] coordinates = splitLine[1].toCharArray();
                    int a = coordinates[3] - 48;
                    int b = coordinates[5] - 48;
                    int c = coordinates[10] - 48;
                    int d = coordinates[12] - 48;
                    Car car = new Car(lineNumber - 17, a, b, c, d);
                    carsList.add(car);
                }
            }
            Parking parking = new Parking(carsList);
            Graph graph = new Graph(parking);
            List<Parking> sol = graph.bfs();
            System.out.println("\n------------- Solution -------------");
            for (Parking sols: sol)
            {   // L = Left, D = Down, R = Right, U = Up
                System.out.println(sols);
            }
        }


        catch(FileNotFoundException ex)
            {ex.printStackTrace();}
        catch(IOException ex) 
            {ex.printStackTrace();}
    }
}

这是使用改编的BFS

的“图表”
package rush.hour;

import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import java.util.Queue;


public class Graph
{
    Parking posDepart;

    public Graph(Parking parking)
    {
        posDepart = parking;
    }

    public List<Parking> bfs()
    {
        List<Parking> res = new ArrayList<>();
        Queue<Parking> queue = new LinkedList<>();
        queue.add(posDepart);
        while (!queue.isEmpty())
        {
            Parking next = queue.remove();
            if (next.isFinal())
            {
                res.add(next);
                return next.getPath();
            }
            next.setChildren();
            for (Parking child : next.children) {
                queue.add(child);
            }
        }
        return res;
    }
}

这是Graph的“节点”,它代表了车上汽车的配置

package rush.hour;

import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;


public class Parking
{
    Parking father = null;
    List<Car> carsList = new ArrayList<>();
    boolean visited = false;
    List<Parking> children = new ArrayList<>();
    List<Character> move = new ArrayList<>();


    public Parking(List<Car> list)
    {
        for (Car car: list)
            carsList.add(car.clone());
    }

    public Parking(Parking vader,List<Character> mov)
    {
        for (Car car: vader.carsList)
            carsList.add(car.clone());
        father = vader;
        move = mov;
    }


    public void getNextParkings(List<List<Character>> moves)
    {   
        children.clear();
        for (int i = 0; i < moves.size(); ++i)
        {
            List<Character> info = moves.get(i);
            Parking nextParking = new Parking(this, info);
            nextParking.carsList.get(info.get(0) - 48).move(info.get(1));
            children.add(nextParking);
        }
    }

    @Override
    public String toString()
    {
        String res = "";
        if (!move.isEmpty())
        {
            res += "Move made to reach this parking:";
            res += move;
            res += "\n";
        }
        for (Car car : carsList)
            res += car.toString();
        return res;
    }

    public boolean isFinal()
    {
        return carsList.get(0).isFinal();
    }

    public void setChildren()
    {
        if (children.isEmpty())
        {
            List<List<Character>> moves = getPossibleMoves();
            getNextParkings(moves);
        }
    }

    public List<List<Character>> getPossibleMoves()
    {
        List<List<Character>> res = new ArrayList<>();
        List<List<Character>> moves;
        for (Car car : carsList)
        {
            moves = car.getPossibleMoves();
            for (int i = 0; i < moves.size(); ++i)
            {
                List<Character> move = moves.get(i);
                if (!hasNeighbour(move.get(0), 
                        move.get(1) - 48, move.get(2) - 48))
                {
                    List<Character> foo = new ArrayList<>(2);
                    foo.add(car.getNumber());
                    foo.add(move.get(0));
                    res.add(foo);
                }
            }
        }
        return res;
    }

    public boolean hasNeighbour(char direction, int x, int y)
    {
        for (Car car : carsList)
        {
            if (direction == 'U')
                if ((car.getX1() == x - 1 && car.getY1() == y) ||
                        (car.getX2() == x - 1 && car.getY2() == y))
                    return true;
            if (direction == 'D')
                if ((car.getX1() == x + 1 && car.getY1() == y) ||
                        (car.getX2() == x + 1 && car.getY2() == y))
                    return true;
            if (direction == 'L')
                if ((car.getX1() == x && car.getY1() == y - 1) ||
                        (car.getX2() == x && car.getY2() == y - 1))
                    return true;
            if (direction == 'R')
                if ((car.getX1() == x && car.getY1() == y + 1) ||
                        (car.getX2() == x && car.getY2() == y + 1))
                    return true;
        }
        return false;
    }

    public List<Parking> getPath()
    {
        Parking temp_father;
        List<Parking> path = new LinkedList<>();
        path.add(this);
        temp_father = this.father;
        while (temp_father != null)
        {
            path.add(0, temp_father);
            temp_father = temp_father.father;
        }
        return path;
    }
}

最后是Car类,这可能对问题不是很重要但仍然

package rush.hour;

import java.util.List;
import java.util.ArrayList;


public class Car
{
    char orientation;
    int carNumber;
    int x1;
    int x2;
    int y1; 
    int y2;

    @Override
    public String toString()
    {
        return "Car n° : " + (carNumber) + " : [(" + (x1) + ", " + y1 + ')' +
                " (" + (x2) + ", " + y2 + ")]" + "\n";
    }

    public Car clone()
    {
        Car c = new Car(carNumber, x1, y1, x2, y2);
        return c;
    }

    public Car(int n, int a, int b, int c, int d)
    {
        carNumber = n;
        if (a <= c)
        {
            x1 = a;
            x2 = c;
        }
        else
        {
            x1 = c;
            x2 = a;
        }
        if (b <= d)
        {
            y1 = b;
            y2 = d;
        }
        else
        {
            y1 = d;
            y2 = b;
        }
        if (x1 == x2)
            orientation = 'H';
        else
            orientation = 'V';
    }

        public char getNumber()
    {
        return Integer.toString(carNumber).charAt(0);
    }

    public int getX1()
    {
        return x1;
    }

    public int getX2()
    {
        return x2;
    }

    public int getY1()
    {
        return y1;
    }

    public int getY2()
    {
        return y2;
    }

    public void move(char direction)
    {
        if (direction == 'U')
        {
            --x1;
            --x2;
        }
        if (direction == 'D')
        {
            ++x1;
            ++x2;
        }
        if (direction == 'L')
        {
            --y1;
            --y2;
        }
        if (direction == 'R')
        {
            ++y1;
            ++y2;
        }
    }

    public boolean isFinal()
    {
        return y2 == 4 && carNumber == 0;
    }


    public List<List<Character>> getPossibleMoves()
    {
        List<List<Character>> res = new ArrayList<>();
        if (orientation == 'H')
        {
            if (y1 != 0)
            {
                List<Character> foo = new ArrayList<>(2);
                foo.add('L');
                foo.add(Integer.toString(x1).charAt(0));
                foo.add(Integer.toString(y1).charAt(0));
                res.add(foo);
            }
            if (y2 != 4)
            {
                List<Character> foo = new ArrayList<>(2);
                foo.add('R');
                foo.add(Integer.toString(x2).charAt(0));
                foo.add(Integer.toString(y2).charAt(0));
                res.add(foo);
            }
        }
        else
        {
            if (x1 != 0)
            {
                List<Character> foo = new ArrayList<>(2);
                foo.add('U');
                foo.add(Integer.toString(x1).charAt(0));
                foo.add(Integer.toString(y1).charAt(0));
                res.add(foo);
            }
            if (x2 != 4)
            {
                List<Character> foo = new ArrayList<>(2);
                foo.add('D');
                foo.add(Integer.toString(x2).charAt(0));
                foo.add(Integer.toString(y2).charAt(0));
                res.add(foo);
            }
        }
        return res;
    }
}

对不起,如果我做了一些明显的样式/编码错误,我更习惯于使用Python / C ++进行编码。有没有办法让这项工作?

1 个答案:

答案 0 :(得分:0)

您需要使用某种类型的数据结构来跟踪已经遍历的路径。哈希表是理想的,并且根据实现将提供O(n)的最坏情况。不是很熟悉Java但是在C ++中我会使用std :: unordered_map,第一个字段是你的电路板状态,第二个字段是那个时候的移动数。我之前已经实现了这个算法,这就是我采用的方法。非常快。