【发布时间】:2014-01-04 01:08:25
【问题描述】:
我正在尝试为这种旅行者问题实现一个简单有效的算法(但这不是“旅行推销员”):
A traveller has to visit N towns, and:
1. each trip from town X to town Y occurs once and only once
2. the origin of each trip is the destination of the previous trip
所以,如果您有例如城镇 A、B、C,
A->B, B->A, A->C, **C->A, B->C**, C->B
不是解决方案,因为您不能先执行 C->A,然后执行 B->C(您需要在两者之间使用 A->B),而:
A->B, B->C, C->B, B->A, A->C, C->A
是一个可接受的解决方案(每个目的地都是下一次旅行的起点)。
下面是一个 Java 插图,以 4 个城镇为例。ItineraryAlgorithm 是在提供回答问题的算法时要实现的接口。如果您将new TooSimpleAlgo() 替换为new MyAlgorithm(),main() 方法将测试您的算法是否存在重复。
package algorithm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Traveller {
private static final String[] TOWNS = new String[] { "Paris", "London", "Madrid", "Berlin"};
public static void main(String[] args) {
ItineraryAlgorithm algorithm = new TooSimpleAlgo();
List<Integer> locations = algorithm.processItinerary(TOWNS);
showResult(locations);
}
private static void showResult(List<Integer> locations) {
System.out.println("The itinerary is:");
for (int i=0; i<locations.size(); i++) {
System.out.print(locations.get(i) + " ");
}
/*
* Show detailed itinerary and check for duplicates
*/
System.out.println("\n");
System.out.println("The detailed itinerary is:");
List<String> allTrips = new ArrayList<String>();
for (int m=0; m<locations.size()-1; m++) {
String trip = TOWNS[locations.get(m).intValue()] + " to "+TOWNS[locations.get(m+1).intValue()];
boolean duplicate = allTrips.contains(trip);
System.out.println(trip+(duplicate?" - ERROR: already done this trip!":""));
allTrips.add(trip);
}
System.out.println();
}
/**
* Interface for interchangeable algorithms that process an itinerary to go
* from town to town, provided that all possible trips are present in the
* itinerary, and only once. Note that after a trip from town A to town B,
* the traveler being in town B, the next trip is from town B.
*/
private static interface ItineraryAlgorithm {
/**
* Calculates an itinerary in which all trips from one town to another
* are done. Trip to town A to town B should occur only once.
*
* @param the
* number of towns to visit
* @return the list of towns the traveler visits one by one, obviously
* the same town should figure more than once
*/
List<Integer> processItinerary(String[] towns);
}
/**
* This algorithm is too simple because it misses some trips! and generates
* duplicates
*/
private static class TooSimpleAlgo implements ItineraryAlgorithm {
public TooSimpleAlgo() {
}
public List<Integer> processItinerary(String[] towns) {
final int nbOfTowns = towns.length;
List<Integer> visitedTowns = new ArrayList<Integer>();
/* the first visited town is town "0" where the travel starts */
visitedTowns.add(Integer.valueOf(0));
for (int i=0; i<nbOfTowns; i++) {
for (int j=i+1; j<nbOfTowns; j++) {
/* travel to town "j" */
visitedTowns.add(Integer.valueOf(j));
/* travel back to town "i" */
visitedTowns.add(Integer.valueOf(i));
}
}
return visitedTowns;
}
}
}
这个示例程序给出以下输出,第一部分是按旅行者访问它们的顺序排列的城镇索引列表(0 代表“巴黎”,1 代表“伦敦”,2 代表“马德里”,3 代表“柏林”)。
The itinerary is:
0 1 0 2 0 3 0 2 1 3 1 3 2
The detailed itinerary is:
Paris to London
London to Paris
Paris to Madrid
Madrid to Paris
Paris to Berlin
Berlin to Paris
Paris to Madrid - ERROR: already done this trip!
Madrid to London
London to Berlin
Berlin to London
London to Berlin - ERROR: already done this trip!
Berlin to Madrid
您建议如何实施 ItineraryAlgorithm?
编辑:如果您愿意,您可以根据需要为最多 4、5、...、最多 10 个城镇提出解决方案。
【问题讨论】:
-
@tom 指的是 P=NP 的东西。在此处阅读更多内容:en.wikipedia.org/wiki/P%3DNP 这并不意味着问题无法解决,它只是意味着您添加到问题集中的每个城市将需要大量资源并且需要成倍增长。这也意味着,在某些问题集大小下,它实际上变得无法解决,因为它需要几个世纪或更长时间才能处理。
-
对于4个城镇的例子,可能的解决方案之一是0131230203210,也就是说Paris->London->Berlin->London->Madrid->Berlin->Paris->Madrid->巴黎->柏林->马德里->伦敦->巴黎
标签: java algorithm strategy-pattern