BFS和A*算法分別解決N-數碼問題

數碼問題求解,分別使用BFS和啓發式搜索實現。java

BFS:求解指定3*3拼圖(8-數碼問題)的最優解。node

    1,isCompleted記錄求解完成狀態;數組

    2,closeList記錄全部訪問過的節點;函數

   3,searchedNodesNum記錄訪問過的節點數;this

  4,solutionPath記錄解路徑。spa

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;
	}


啓發式搜索:code

訪問節點數大於30000個則認爲搜索失敗。排序

 函數結束後:isCompleted記錄了求解完成狀態;索引

                          closeList記錄了全部訪問過的節點;element

                    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);
	}
相關文章
相關標籤/搜索