我正试图了解大学的TSP计划, 我不得不承认我发现它非常困难。
基本上我有一个Lat值数组和一个Lng值数组,使用hasrsine,我已将距离转换为矩阵。
现在从哪里开始?
我必须找到最短的距离,访问所有80个城镇。我想到最好的方法来做到这一点。我应该制作最近邻算法吗?
我应该只存储排列和总距离。
或者,还有更好的方法?我不得不承认,我认为这对一年级学生来说有点困难!
无论如何这里是我的代码,它很糟糕,小程序等给了我们。
public class Brain {
//These are the names of the 80 towns and their north and west GPS co-ordinates
static double north[] = {53.855,52.794,54.350,53.433,52.992,54.117,53.328,54.800,54.863,55.071,54.502,54.343,51.746,54.660,51.680,54.597,53.091,53.175,55.136,52.831,53.976,53.944,53.861,53.991,51.622,52.354,51.897,54.996,54.322,53.714,53.348,54.009,54.500,52.085,53.345,52.846,52.502,54.345,53.272,52.677,53.728,53.106,52.648,52.059,51.708,53.783,54.851,54.957,55.053,52.665,52.447,53.727,53.197,51.904,54.750,52.131,53.382,52.266,54.248,53.116,53.522,52.863,52.396,54.210,52.451,54.590,53.633,52.714,54.267,53.245,54.830,52.679,52.474,52.268,53.515,53.267,52.257,53.800,52.334,51.952};
static double west[] = {-6.538,-6.165,-6.655,-7.950,-6.987,-9.167,-8.219,-7.790,-6.284,-6.508,-8.190,-6.260,-8.735,-5.670,-9.453,-5.930,-7.913,-6.525,-7.456,-6.932,-6.719,-8.095,-9.299,-7.360,-8.886,-7.712,-8.470,-7.307,-5.703,-6.350,-6.260,-6.405,-6.770,-7.640,-7.051,-8.981,-6.566,-7.640,-9.049,-6.292,-6.878,-6.065,-7.256,-9.507,-8.531,-8.917,-5.811,-7.720,-6.946,-8.624,-9.486,-7.800,-8.567,-8.957,-6.610,-8.642,-6.591,-8.270,-6.971,-7.324,-7.338,-8.200,-6.945,-5.882,-9.055,-7.290,-8.183,-8.869,-8.483,-9.306,-7.470,-7.814,-8.162,-9.696,-8.851,-7.500,-7.129,-9.533,-6.458,-7.846};
String names[] = {"Ardee","Arklow","Armagh","Athlone","Athy","Ballina","Ballinasloe","Ballybofe","Ballymena","Ballymoney","Ballyshannon","Banbridge","Bandon","Bangor","Bantry","Belfast","Birr","Blessington","Buncrana","Carlow","Carrickmacross","Carrick-On-Shannon","Castlebar","Cavan","Clonakilty","Clonmel","Cork","Derry","Downpatrick","Drogheda","Dublin","Dundalk","Dungannon","Dungarvan","Edenderry","Ennis","Enniscorthy","Enniskillen","Galway","Gorey","Kells","Kilcoole","Kilkenny","Killarney","Kinsale","Knock","Larne","Letterkenny","Limavady","Limerick","Listowel","Longford","Loughrea","Macroom","Magherafelt","Mallow","Maynooth","Mitchelstown","Monaghan","Mountmellick","Mullingar","Nenagh","New-Ross","Newcastle","Newcastle-West","Omagh","Roscommon","Shannon","Sligo","Spiddal","Strabane","Thurles","Tipperary","Tralee","Tuam","Tullamore","Waterford","Westport","Wexford","Youghal"};
static double[][] matrix = new double[80][80];
boolean visit[]=new boolean[80];
boolean valid = true;
public static void fillmatrix (){
double tote = 0;
for(int i=1;i<80;i++){
for(int j=1;j<80;j++){
matrix[i][j]=getDistance(north[i],west[j],north[j],west[j]);
}
}
}
public String compute () {
String solution ="";
for (int i=0;i<80;i++){
solution+=(char)(i+40);
}
solution+="Anything you add on after the 80 characters will be " +
"printed in the textbox (e.g. you can compute the distance)";
return solution;
}
public static double getDistance(double lat1, double lon1, double lat2, double lon2){
double R = 6371;
double dLat = Math.toRadians((lat2-lat1));
double dLon = Math.toRadians((lon2-lon1));
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double d = R * c;
return d;
}
}
答案 0 :(得分:1)
除了最微小的情况之外,检查所有排列对于任何事情来说都是非常昂贵的。
幸运的是,TSP有一大堆着名的启发式算法。 Take your pick
答案 1 :(得分:1)
解决最近邻启发式问题的最佳方法是将算法分解为子问题。
接下来,解决每个子问题。
然后,考虑伪代码并尝试编写Java代码。
答案 2 :(得分:0)
关于SourceCode
首先,我可能会建议您将城市坐标的定义更改为城市类,并且,由于您预先定义了城市,您可能希望将其“导出”到外部文件中并将其加载到文件中beggining。例如,
public class City{
public double North;
public double West;
public String Name;
public double getDistanceToCity(City target){
double R = 6371;
double dLat = Math.toRadians((target.North-this.North));
double dLon = Math.toRadians((target.West-this.West));
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(this.North)) * Math.cos(Math.toRadians(this.West)) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double d = R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return d;}}
然后,例如,在将您的文件读入“ArrayList Cities”之后,您将通过以下方式对您的矩阵进行打包:
double[][] distances = new double[Cities.size()][Cities.size()];
int i=0;
int j=0;
for(City start:Cities){
for(City end:Cities){
distances[i][j]=start.getDistanceToCity(end);
j++;}
i++;}
获得相同的矩阵。在这种情况下,您可以更改输入数据大小,例如测试您的算法与10个城市的正确性,并且在所有工作完成后运行80.此外,在这种情况下,您将亲眼看到这个问题的硬度 - 简单在40和41城市运行......
接下来,关于算法......
这是NP难题,所以你的排列会很长时间。我会建议Held-Karp算法,这个算法要快得多,但很难实现,需要大量内存。 (例如,建议的方法if(n * n * 2 ^ n),对于n = 80是10 ^ 27,并且排列是n!,其中10 ^ 121对于n = 80 - 我指的是解决任务所需的操作)
无论如何,现在最好的解决方案是线性编程(不记得确切的方法,但是......)。你可以找一些考虑使用图表方法的算法。