Java 求部分定向图中所有可能的哈密顿圈
这是我在图中求哈密顿圈的算法:Java 求部分定向图中所有可能的哈密顿圈,java,hamiltonian-cycle,Java,Hamiltonian Cycle,这是我在图中求哈密顿圈的算法: private SolutionArray solution; private int V, pathCount; private int[] path; private int[][] graph; /** * Constructor */ public ConcreteSolver() { solution = new SolutionArray(); } @Override public SolutionArray solve(PathMat
private SolutionArray solution;
private int V, pathCount;
private int[] path;
private int[][] graph;
/**
* Constructor
*/
public ConcreteSolver() {
solution = new SolutionArray();
}
@Override
public SolutionArray solve(PathMatrix input) {
V = input.getNbVertex();
path = new int[V];
/** Set all path to non-visited **/
boolean[] visited = new boolean[V];
for (int i = 0; i < V; i++) {
visited[i] = false;
}
Arrays.fill(path, -1);
graph = input.getMatrix();
try {
path[0] = input.getFirstVertex();
pathCount = 1;
findPaths(0);
System.out.println("No solution");
} catch (Exception e) {
System.out.println("\nSolution found");
//input.printMatrix();
displayAndWrite();
}
return solution;
}
/**
* function to find paths recursively
*/
private void findPaths(int vertex) throws Exception {
/** solution **/
if (graph[vertex][0] >= 1 && pathCount == V) {
throw new Exception();
}
/** all vertices selected but last vertex not linked to 0 **/
if (pathCount == V)
return;
for (int v = 0; v < V; v++) {
/** if connected **/
if (graph[vertex][v] >= 1) {
/** add to path **/
path[pathCount++] = v;
/** if vertex not already selected solve recursively **/
if (!isPresent(v))
findPaths(v);
/** remove path **/
path[--pathCount] = -1;
}
}
}
/**
* function to check if path is already selected
*/
private boolean isPresent(int v) {
for (int i = 0; i < pathCount - 1; i++)
if (path[i] == v)
return true;
return false;
}
private SolutionArray解决方案;
私有int V,路径计数;
私有int[]路径;
私有int[][]图;
/**
*建造师
*/
公营机构({
溶液=新溶液射线();
}
@凌驾
公共解决方案光线解算(路径矩阵输入){
V=input.getNbVertex();
路径=新整数[V];
/**将所有路径设置为“未访问”**/
布尔[]访问=新布尔[V];
对于(int i=0;i=1&&pathCount==V){
抛出新异常();
}
/**已选定所有顶点,但最后一个顶点未链接到0**/
if(路径计数==V)
返回;
对于(int v=0;v=1){
/**添加到路径**/
路径[pathCount++]=v;
/**如果尚未选择顶点,则递归求解**/
如果(!isPresent(v))
findPaths(五);
/**删除路径**/
路径[--pathCount]=-1;
}
}
}
/**
*函数检查是否已选择路径
*/
私有布尔值isPresent(int v){
对于(int i=0;i
我能找到一个第一哈密顿循环。是否有可能对其进行调整以找到图中所有可能的哈密顿圈
输入是一个非对称矩阵(节点之间的一些链接是单向的),一些节点可能有2个或3个到其他节点的链接
多谢各位
编辑:
为了澄清,该算法已经可以找到一个解决方案,但无法找到第二个解决方案,以此类推。从阅读中可以看出,使用bactracking*可以解决这个问题,但我不确定它是否可以添加到我已经拥有的内容中。目前,您有一个数组来捕获当前正在探索的路径。您的
display和write
方法可能会使用此信息打印解决方案
为了记录所有的解,当你找到哈密顿循环时,你需要一个路径的副本
有点像:
private static final int MAX_SOLUTIONS = 100;
private int[][] solutions = new int[MAX_SOLUTIONS][];
private int solutionCount = 0;
private void addSolution(int[] path) {
if (solutionCount < MAX_SOLUTIONS)
solutions[solutionCoun++] = Arrays.copyOf(path, path.length);
}
private static final int MAX_SOLUTIONS=100;
私有int[]solutions=新int[MAX_solutions][];
私有int solutionCount=0;
私有void addSolution(int[]路径){
if(溶液计数<最大溶液)
solutions[solutionCoun++]=Arrays.copyOf(path,path.length);
}
您需要在当前处理异常的递归方法中调用addSolution
顺便说一句,几乎所有有经验的Java程序员都认为抛出一个表示成功的异常是糟糕的风格。我希望在其他语言中也是如此-异常用于异常:-)现在,当检测到一个循环时,您会抛出一个异常:
if (graph[vertex][0] >= 1 && pathCount == V) {
throw new Exception();
}
除了抛出一个异常是错误的,因为它并不是一个真正的异常情况——请看我对这个问题的评论——你所需要做的就是在你发现这个周期没有那么“爆炸性”时采取行动
如果不知道Solutionaray的定义,我就无法利用它给出答案
由于您不知道可以找到多少个周期,请添加列表
,以收集您的解决方案:
private List<int[]> solutions = new ArrayList<>();
因为这只是从方法返回,而不是抛出异常,所以调用函数的执行将继续检查下一个可能的路径
获取路径的副本很重要,因为否则,您只需添加对用作工作副本的数组的引用,因此它们都将是同一个数组,并且,由于您可能会在之后更新它,因此最后甚至不一定包含有效的解决方案
然后,在main方法中,只需检查此列表是否为非空:
if (!solutions.isEmpty()) {
System.out.println("\nSolution(s) found");
displayAndWrite();
}
与其说是对您的问题的评论,不如说是对您的实现的评论:您不应该使用异常来表示已经找到了解决方案。例外是指例外的事物。见第二版第57项。调用此方法有两种结果:void和Exception。你可以很容易地将其设为假或真,或者一个enum没有被发现和发现,这将更容易摸索。这很好,但它没有告诉我如何检测多个解决方案周期。一旦我找到了,该怎么处理them@JulioQc请仔细阅读我的答案并思考控制流程。具体来说,为什么您的代码在找到一个解决方案后会停止,而这可能不会停止?
if (!solutions.isEmpty()) {
System.out.println("\nSolution(s) found");
displayAndWrite();
}