对于一个学校项目,我正在尝试对旅行商问题实施蛮力算法。我想做的是,输入一个代表点数的整数,对于每个点,将给出一个随机的x和y值,该值代表它们在2D平面上的位置。在所有点都初始化之后,该算法将计算从点1开始的每条路线的距离,然后对所有不同的可能性进行置换。
更新1:
因此,我对Point.java和PointManager.java类进行了编码,目的是初始化这些点并将它们保留在arraylist中。 他们看起来像这样 Point.java:
public class Point {
int x;
int y;
//Constructs a random Point
public Point(){
this.x = (int)(Math.random()*200);
this.y = (int)(Math.random()*200);
}
//gives Point X Position
public int getPosX(){
return this.x;
}
//gives Point Y Position
public int getPosY(){
return this.y;
}
public double distance(Point point){
int distance_x = Math.abs(getPosX() - point.getPosX());
int distance_y = Math.abs(getPosY() - point.getPosY());
double distance = Math.sqrt((distance_x * distance_x) + (distance_y * distance_y));
return distance;
}
}
PointManager.java
import java.util.ArrayList;
public class PointManager {
// Holds our cities
private static ArrayList destinationPoints = new ArrayList<Point>();
// Adds a destination city
public static void addPoint(Point point) {
destinationPoints.add(point);
}
// Get a city
public static Point getPoint(int index){
return (Point)destinationPoints.get(index);
}
// Get the number of destination cities
public static int numberOfPoints(){
return destinationPoints.size();
}
}
现在的问题是,我将如何继续对可能性进行不同的排列,以及如何检查路线中是否已使用了某个点?
答案 0 :(得分:0)
最直接的解决方案是使用递归:
它跟踪哪些点已访问,哪些仍需要访问。 在每次调用时,它仅使用所有可能的“下一个点”扩展当前路径。
只要没有其他点要包含,它将打印路径。
private static void branch(Set<Point> todoPoints, List<Point> donePoints){
if(todoPoints.isEmpty()){
// measure distance
double totalDistance = 0;
for (int i = 0; i < donePoints.size(); i++) {
totalDistance += donePoints.get(i).distance(donePoints.get((i+1) % donePoints.size()));
}
System.out.println("Solution found");
System.out.println("\t" + donePoints);
System.out.println("\t"+totalDistance);
}else{
for(Point nextPoint : todoPoints){
// add point
donePoints.add(nextPoint);
// recurse
Set<Point> tmp = new HashSet<>(todoPoints);
tmp.remove(nextPoint);
branch(tmp, donePoints);
// remove point
donePoints.remove(nextPoint);
}
}
}
当然可以改进此策略。 我们可以跟踪当前的最小距离,并使用它。 例如,延伸超出当前最小距离的路径没有附加值。
它看起来像这样:
private static void branch2(Set<Point> todoPoints, List<Point> donePoints, double dist){
if(todoPoints.isEmpty()){
dist += donePoints.get(0).distance(donePoints.get(donePoints.size()-1));
CURRENT_MIN_DIST = java.lang.Math.min(CURRENT_MIN_DIST, dist);
System.out.println("Solution found");
System.out.println("\t" + donePoints);
System.out.println("\t"+dist);
}else{
for(Point nextPoint : todoPoints){
// add point
donePoints.add(nextPoint);
// update distance
dist += (donePoints.size() > 1 ? donePoints.get(donePoints.size()-2).distance(donePoints.get(donePoints.size()-1)) : 0);
// we do not recurse if the current distance is already bigger than a known minimum
if(dist > CURRENT_MIN_DIST)
continue;
// recurse
Set<Point> tmp = new HashSet<>(todoPoints);
tmp.remove(nextPoint);
branch2(tmp, donePoints, dist);
// remove point
donePoints.remove(nextPoint);
}
}
}
最后,进一步的改进是跟踪完成当前路径所需添加的最小距离。
然后,您可以进一步修剪此递归。 您可以检查
当前距离+完成所需的最小距离<当前最小距离
可以这样实现:
private static void branch3(Set<Point> todoPoints, List<Point> donePoints, double dist){
if(todoPoints.isEmpty()){
dist += donePoints.get(0).distance(donePoints.get(donePoints.size()-1));
CURRENT_MIN_DIST = java.lang.Math.min(CURRENT_MIN_DIST, dist);
System.out.println("Solution found");
System.out.println("\t" + donePoints);
System.out.println("\t"+dist);
}else{
for(Point nextPoint : todoPoints){
// add point
donePoints.add(nextPoint);
// update distance
dist += (donePoints.size() > 1 ? donePoints.get(donePoints.size()-2).distance(donePoints.get(donePoints.size()-1)) : 0);
// we do not recurse if the current distance is already bigger than a known minimum
if(dist > CURRENT_MIN_DIST)
continue;
if(dist + minDistToFinish(todoPoints) > CURRENT_MIN_DIST)
continue;
// recurse
Set<Point> tmp = new HashSet<>(todoPoints);
tmp.remove(nextPoint);
branch3(tmp, donePoints, dist);
// remove point
donePoints.remove(nextPoint);
}
}
}
相关方法如下:
private static double minDistToFinish(Set<Point> todoPoints){
double distToFinish = 0;
for(Point p1 : todoPoints){
double d = Double.MAX_VALUE;
for(Point p2 : todoPoints){
if(p1.equals(p2))
continue;
d = java.lang.Math.min(d, p1.distance(p2));
}
distToFinish += d;
}
return distToFinish;
}