标签:
数码问题求解,分别使用BFS和启发式搜索实现。
BFS:求解指定3*3拼图(8-数码问题)的最优解。
1,isCompleted记录求解完成状态;
2,closeList记录所有访问过的节点;
3,searchedNodesNum记录访问过的节点数;
4,solutionPath记录解路径。
public boolean BFSearch() throws IOException { // 将搜索过程写入D://BFSearchDialog.txt String filePath = "BFSearchDialog.txt"; PrintWriter pw = new PrintWriter(new FileWriter(filePath)); // ************************************* JigsawNode beginnode = getBeginJNode(); openList.add(beginnode); isCompleted = false; // 判断广搜结束条件 while (!openList.isEmpty()) { // 判断是否到达目标状态 JigsawNode root = openList.firstElement(); currentJNode = root; if (getCurrentJNode().equals(getEndJNode())) { isCompleted = true; break; } // 访问openList的第一个节点,将相邻的 且未被访问的(在closeList中找不到)的节点加入openList Vector<JigsawNode> neighbornodes = new Vector<JigsawNode>(); neighbornodes = findFollowJNodes(root); openList.addAll(neighbornodes); openList.removeElementAt(0); closeList.add(root); searchedNodesNum++; } if (isCompleted) { calSolutionPath(); } // ************************************* this.printResult(pw); pw.close(); System.out.println("Record into " + filePath); return isCompleted; }
启发式搜索:
访问节点数大于30000个则认为搜索失败。
函数结束后:isCompleted记录了求解完成状态;
closeList记录了所有访问过的节点;
searchedNodesNum记录了访问过的节点数;
solutionPath记录了解路径。
public boolean ASearch() throws IOException{ // 将搜索过程写入ASearchDialog.txt String filePath = "ASearchDialog.txt"; PrintWriter pw = new PrintWriter(new FileWriter(filePath)); // 访问节点数大于25000个则认为搜索失败 int maxNodesNum = 25000; // 用以存放某一节点的邻接节点 Vector<JigsawNode> followJNodes = new Vector<JigsawNode>(); // 重置求解完成标记为false isCompleted = false; // (1)将起始节点放入openList中 this.sortedInsertOpenList(this.beginJNode); // (2) 如果openList为空,或者访问节点数大于maxNodesNum个,则搜索失败,问题无解;否则循环直到求解成功 while (this.openList.isEmpty() != true && searchedNodesNum <= maxNodesNum) { // (2-1)访问openList的第一个节点N,置为当前节点currentJNode // 若currentJNode为目标节点,则搜索成功,设置完成标记isCompleted为true,计算解路径,退出。 this.currentJNode = this.openList.elementAt(0); if (this.currentJNode.equals(this.endJNode)){ isCompleted = true; this.calSolutionPath(); break; } // (2-2)从openList中删除节点N,并将其放入closeList中,表示以访问节点 this.openList.removeElementAt(0); this.closeList.addElement(this.currentJNode); searchedNodesNum++; // 记录并显示搜索过程 pw.println("Searching.....Number of searched nodes:" + this.closeList.size() + " Current state:" + this.currentJNode.toString()); System.out.println("Searching.....Number of searched nodes:" + this.closeList.size() + " Current state:" + this.currentJNode.toString()); // (2-3)寻找所有与currentJNode邻接且未曾被访问的节点,将它们按代价估值从小到大排序插入openList中 followJNodes = this.findFollowJNodes(this.currentJNode); while (!followJNodes.isEmpty()) { this.sortedInsertOpenList(followJNodes.elementAt(0)); followJNodes.removeElementAt(0); } } this.printResult(pw); // 记录搜索结果 pw.close(); // 关闭输出文件 System.out.println("Record into " + filePath); return isCompleted; } /* 计算并修改状态节点jNode的代价估计值:f(n)=s(n)。 * s(n)代表后续节点不正确的数码个数 * @param jNode - 要计算代价估计值的节点;此函数会改变该节点的estimatedValue属性值。 */ private void estimateValue(JigsawNode jNode) { int fn = 0; // 后续节点不正确的数码个数 int s = 0; // 所有 放错位的数码与其正确位置的距离 之和 int errordis = 0; // 所有 放错位的数码 个数 int errornum = 0; int index; // 空格的索引下标 int spaceindex = 0; // 该Node的数组 int[] nodestate = jNode.getNodesState(); int dimension = JigsawNode.getDimension(); for(index =1 ; index<dimension*dimension; index++){ if(nodestate[index]+1!=nodestate[index+1]) { s++; } } for (index =1 ; index<dimension*dimension; index++) { if(index != nodestate[spaceindex] && nodestate[index] != index) { errornum++; // 求解曼哈顿距离 // 当前坐标 int cx, cy, dx,dy; cx = (index - 1) / dimension; cy = (index -1 ) % dimension; dx = (nodestate[index] - 1) / dimension; dy = (nodestate[index] -1) % dimension; errordis = errordis+Math.abs(dx-cx) + Math.abs(dy-cy); } } fn = 2*s + errordis + errornum; jNode.setEstimatedValue(fn); }
标签:
原文地址:http://my.oschina.net/u/2348884/blog/407911