我正在尝试使用广度优先搜索来实现高峰时间求解算法,以遍历不同路径的图形,在找到解决方案时停止。
经过多次测试,我遇到了一个我不知道如何解决的问题。当有解决方案时,算法运行得很好,但是当找不到任何一个时,它只是无休止地循环,因为它重新创建包含与旧信息相同信息的“节点”,而不是如果信息是相同。当它发现没有更多的可能性时,我怎么能让它停下来?
以下是我为解算器使用的类:
这是我操作的主要类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 ++进行编码。有没有办法让这项工作?
答案 0 :(得分:0)
您需要使用某种类型的数据结构来跟踪已经遍历的路径。哈希表是理想的,并且根据实现将提供O(n)的最坏情况。不是很熟悉Java但是在C ++中我会使用std :: unordered_map,第一个字段是你的电路板状态,第二个字段是那个时候的移动数。我之前已经实现了这个算法,这就是我采用的方法。非常快。