相似迷宮問題

 


package com.java.study;
import java.util.*;
/*
* 假設有機器人坐在X*Y網格左上角,機器人要從(0,0)走到(X,Y),
* 假設有些點爲禁區,機器 人不能踏足,設計一種算法,找出一條路徑,讓機器人從左上角移動到右下解。
* 例:
0000000000
0000000000
0010101011
1101001000
其中1爲禁區
*/
public class MysteryGong {
public static class PathPoint{
public int x; //第x行
public int y; //第y列
public int direct; //方向 0表示向下,1表示向右
public int counter;//該位置通過的次數
public PathPoint(int x,int y,int direct,int counter){
this.x=x;this.y=y;this.direct=direct;this.counter=counter;
}

}
public static void main(String[] args) {

int array[][]={
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,1,0,1,0,1,0,1,1},
{1,1,0,1,0,0,1,0,0,0}
};//風格以二維數組形式存儲

findPath1(array);
findPath2(array);
}//採用回溯的方法
public static void findPath1(int[][] array){
int m=array.length; //總行數
int n=array[0].length;//總列數
int right=1;
int down=0;
Deque<PathPoint> stack=new LinkedList<PathPoint>();
stack.push(new PathPoint(0,0,0,0));
boolean status=false;
while(!stack.isEmpty()){
PathPoint point=stack.pop(); //pop出來一次,表示訪問一次
if(point.x==m-1 && point.y==n-1){
status=true; //走到右下角時,找到路徑
stack.push(point);//維護路徑完整性
break;
}else{
if(array[point.x][point.y]!=1){ //該點不是阻塞點
if(point.counter!=2){ //當回溯到該點時,若counter==2,表示該點已走過兩次,即向右向下都試過了,刪除該點
if(!(point.x==m-1 || point.y==n-1)){
stack.push(new PathPoint(point.x,point.y,point.direct+1,point.counter+1));//該點位置訪問次數加1,方向標號+1
if(point.direct==0){ //表示當前要向下走,
stack.push(new PathPoint(point.x+1,point.y,0,0));
}else{ //表示當前要向右走
stack.push(new PathPoint(point.x,point.y+1,0,0));

}
}
//處理最後一行
if(point.x==m-1){ //最後一行,只能向右走
stack.push(new PathPoint(point.x,point.y+1,right,0));
}
//處理最後一列的狀況
if(point.y==n-1){ //到達最後一列,只能向下走
stack.push(new PathPoint(point.x+1,point.y,down,0));
}java

}
}
}
}
if(status==false){
System.out.println("不存在知足條件的路徑");
}else{
//輸出棧中路徑
System.out.println("找到一條知足條件的路徑 :");
printPath(stack);
}
}
public static void printPath(Deque<PathPoint> stack){
if(stack.isEmpty()) return;
PathPoint point=stack.pop();
printPath(stack);
System.out.print("("+point.x+","+point.y+")");
}
/*
通常遞歸方法 :從終點往回走,從最後一點開始,試着找出一條到其相鄰點的路徑
*/
public static void getPath1(int x,int y,ArrayList<Point> path){
Point p=new Point(x,y);
path.add(p);
if(x==0 &&y ==0) return true;
bolean success=false;
if(x>=1 && isFree(x-1,y)){ //試着向左走
success=getPath1(x-1,y,path);
}
if(!success && y>=1 && isFree(x,y-1)){
success=getPath(x,y-1,path);
}
if(!success)
path.add(p); //錯了,最好不要走這裏。
return success;
}
/*採用動態規劃方法 : 通常遞歸方法 +緩存結果
使用緩存記錄已走過的點。以防再次走
效果同回溯相同,只是實現時更加簡單
*/
public static void findPath3(int x,int y,ArrayList<Point> path,Hasthtable<Point,boolean> cache){
Point p=new Point(x,y);
if(cache.contains(key)) { //已訪問過這個點
return cache.get(p);
}
path.add(p);
if(x==0 &&y ==0) return true; //找到一條路徑
if(x>=1 && isFree(x-1,y)){ //試着向左走
success=getPath1(x-1,y,path,cache);
}
if(!success && y>=1 && isFree(x,y-1)){
success=getPath(x,y-1,path,cache);
}
if(!success)
path.add(p); //錯了,最好不要走這裏。
cache.put(p,succcess);
return success;
}
}
}算法

評: 採用通常遞歸方法 : 相似於窮舉法   實現簡單數組

採用回溯:用棧來實現,能夠保存以前的結果   迭代方式 實現複雜緩存

採用動態規劃:通常遞歸法+緩存結果  效果等同於回溯   實現簡單this

相關文章
相關標籤/搜索