迷宫问题:
一张地图上有若干障碍物,表示不能通过。给定起点和终点,要求找到一条从起点到终点的路径。
抽象:
把地图抽象为n*m的布尔矩阵。true表示可以通过,false表示不能通过。
算法思路:
- 维护两个列表,open和close。
- 从起点开始,先将起点加入open列表。算出其上下左右的位置离终点的距离,并让这些点都指向起点,放入open列表里。将起点放入close列表。
- 选择open列表中距离最短的点,对于其上下左右的位置,如果其既不在open列表中又不在close列表中,则计算其距离,并让这些点都指向选中的点,放入open列表中。刚才选中的点放入close列表中。
- 重复步骤3,直到终点被放入close列表中。
- 从终点开始,查找其指向的点,这样一路追溯到起点,则为一条可行路径。
距离的计算:公式 F = G + H
- F代表预测的通过这个点的路径总长度
- G代表从起点到这个点已经走过的长度。用该点指向的点的G加上1
- H为预测的从该点到终点所需距离。其中一种方法:用两个点之间纵坐标差值的绝对值和横坐标差值的绝对值相加而得(曼哈顿方法)
package a_star;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class SimplePuzzle {
class Position {
int x;
int y;
Position lastPosition;
int pastDistance = 0;
int predictDistance;
Position(int x, int y, Position lastPosition) {
this.x = x;
this.y = y;
this.lastPosition = lastPosition;
if(lastPosition != null)
pastDistance = lastPosition.pastDistance + 1;
predictDistance = Math.abs(endx - x) + Math.abs(endy - y);
}
int distance(){
return pastDistance + predictDistance;
}
}
boolean[][] map;
boolean[][] used;
int startx, starty;
int endx, endy;
List<Position> open;
Position openGhost;
boolean endReached = false;
public static void main(String[] args) throws IOException {
new SimplePuzzle().find("/Users/yanning/Development/JAVA_SE_WORKSPACE/Algorithm/map.txt");
}
public void find(String file) throws IOException {
initiate(file);
Position start = new Position(startx, starty, null);
Position end = null;
open.add(start);
while(true) {
Position chosed = open.remove(0);
if(chosed.lastPosition!=null)
System.out.println("choosed: ["+chosed.lastPosition.x+","+chosed.lastPosition.y+"]<-(" + chosed.x+","+chosed.y+")");
if(chosed.x == endx && chosed.y == endy) {
end = chosed;
break;
}
if(valid(chosed.x-1, chosed.y)) {
addToOpenList(new Position(chosed.x-1, chosed.y, chosed));
}
if(valid(chosed.x+1, chosed.y)) {
addToOpenList(new Position(chosed.x+1, chosed.y, chosed));
}
if(valid(chosed.x, chosed.y-1)) {
addToOpenList(new Position(chosed.x, chosed.y-1, chosed));
}
if(valid(chosed.x, chosed.y+1)) {
addToOpenList(new Position(chosed.x, chosed.y+1, chosed));
}
Iterator<Position> itr = open.iterator();
System.out.print("openList: ");
while(itr.hasNext()) {
Position tmp = itr.next();
System.out.print("("+tmp.x+", "+tmp.y+")*"+tmp.distance()+" -> ");
}
System.out.println("\n------------------");
}
Position tmp = end;
System.out.println("path: ");
while(tmp != null) {
System.out.print("("+tmp.x+", "+tmp.y+") <- ");
tmp = tmp.lastPosition;
}
}
void initiate(String file) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(file));
String[] tmp;
int n = Integer.parseInt(br.readLine());
int m = Integer.parseInt(br.readLine());
map = new boolean[n][m];
used = new boolean[n][m];
for(int i = 0; i < n; i++) {
tmp = br.readLine().split(",");
if(tmp.length != m){
System.err.println("Bad input file");
System.exit(-1);
}
for(int j = 0; j < m; j++) {
map[i][j] = (tmp[j].equals("0")) ? false : true;
used[i][j] = false;
}
}
tmp = br.readLine().split(",");
startx = Integer.parseInt(tmp[0]);
starty = Integer.parseInt(tmp[1]);
tmp = br.readLine().split(",");
endx = Integer.parseInt(tmp[0]);
endy = Integer.parseInt(tmp[1]);
open = new LinkedList<Position>();
}
void addToOpenList(Position p) {
used[p.x][p.y] = true;
Iterator<Position> itr = open.iterator();
int index = -1;
while(itr.hasNext()) {
Position tmp = itr.next();
index++;
if(p.distance() <= tmp.distance()) {
open.add(index, p);
return;
}
}
open.add(p);
}
boolean valid(int x, int y) {
if(x < 0 || x >= map.length || y < 0 || y >= map[0].length)
return false;
if(map[x][y] || used[x][y])
return false;
return true;
}
}
输入:map.txt
5
5
0,0,0,0,0
0,0,1,0,0
0,0,1,0,0
0,0,1,0,0
0,0,0,0,0
2,0
1,4
输出:
openList: (2, 1)*5 -> (1, 0)*5 -> (3, 0)*7 -> ------------------
choosed: [2,0]<-(2,1)
openList: (1, 1)*5 -> (1, 0)*5 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [2,1]<-(1,1)
openList: (1, 0)*5 -> (0, 1)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [2,0]<-(1,0)
openList: (0, 0)*7 -> (0, 1)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [1,0]<-(0,0)
openList: (0, 1)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [1,1]<-(0,1)
openList: (0, 2)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [0,1]<-(0,2)
openList: (0, 3)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [0,2]<-(0,3)
openList: (0, 4)*7 -> (1, 3)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [0,3]<-(0,4)
openList: (1, 4)*7 -> (1, 3)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [0,4]<-(1,4)
path:
(1, 4) <- (0, 4) <- (0, 3) <- (0, 2) <- (0, 1) <- (1, 1) <- (2, 1) <- (2, 0) <-