A*算法简介
A*算法相比其他算法來說,特點是具有方向性!
如何具有方向性呢,這就有關它的代價函數了,它的代價函數分為當前代價和預估代價
當前代價 即起點到當前格子已經走了多少步
預估代價:表示從當前方塊到目的地方塊大概需要走多少步,并不是精確的數值,一般用于參考指導算法去優先搜索更有希望的路徑。
最常用到的預估代價有歐幾里德距離,即兩點之間的直線距離,還有便是最簡單的曼哈頓距離,也就是兩點在水平方向上的總和。
在當前位置,將當前代價和預估代價相加,所得代價最低的即位下一步的最優解。
普通A*算法,八個方向
public class AStarAlgorithm {private static final int[][] DIREC = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1},{1, 0}, {1, -1}, {0, -1}, {-1, -1}};static double temp_x = 0;static double temp_y = 0;static double result = 0;static List<List<Integer>> list_fin;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("please enter (rows cols x1 y1 x2 y2): ");final int rows = scanner.nextInt();final int cols = scanner.nextInt();int x1 = scanner.nextInt();int y1 = scanner.nextInt();int x2 = scanner.nextInt();int y2 = scanner.nextInt();scanner.close();// generate a two-dimension array filled with 0int map[][] = new int[rows][cols];for (int i = 0; i < rows; i++) {int tmp[] = new int[cols];Arrays.fill(tmp, 0);map[i] = tmp;}int midr = rows / 2;int midc = cols / 2;/*map[midr - 1][midc] = 1;map[midr][midc] = 1;map[midr + 1][midc] = 1;*/// for (int i = 1; i < rows - 1; i++) { // map[i][midc] = 1; // }map[2][6] = 1;map[3][6] = 1;map[4][6] = 1;map[5][6] = 1;map[6][6] = 1;findPath(map, x1, y1, x2, y2);System.out.println(result);}private static void findPath(int[][] map, int x1, int y1, int x2, int y2) {List<Position> openList = new ArrayList<Position>();List<Position> closeList = new ArrayList<AStarAlgorithm.Position>();boolean findFlag = false;Position termPos = null;// 起始點Position startPos = new Position(x1, y1, calcH(x1, y1, x2, y2));openList.add(startPos);do {// 通過在開啟列表中找到F值最小的點作為當前點Position currentPos = openList.get(0);for (int i = 0; i < openList.size(); i++) {if (currentPos.F > openList.get(i).F) {currentPos = openList.get(i);}}// 將找到的當前點放到關閉列表中,并從開啟列表中刪除closeList.add(currentPos);openList.remove(currentPos);//遍歷當前點對應的8個相鄰點for (int i = 0; i < DIREC.length; i++) {//8個方向都去試了一遍int tmpX = currentPos.row + DIREC[i][0];int tmpY = currentPos.col + DIREC[i][1];if (tmpX < 0 || tmpX >= map.length || tmpY < 0 || tmpY >= map[0].length) {continue;}//創建對應的點Position tmpPos = new Position(tmpX, tmpY, calcH(tmpX, tmpY, x2, y2), currentPos);//map中對應的格子中的值為1(障礙), 或對應的點已經在關閉列表中if (map[tmpX][tmpY] == 1 || closeList.contains(tmpPos)) {continue;}//如果不在開啟列表中,則加入到開啟列表if (!openList.contains(tmpPos)) {openList.add(tmpPos);} else {// 如果已經存在開啟列表中,則用G值考察新的路徑是否更好,如果該路徑更好,則把父節點改成當前格并從新計算FGHPosition prePos = null;for (Position pos : openList) {if (pos.row == tmpX && pos.col == tmpY) {prePos = pos;break;}}if (tmpPos.G < prePos.G) {prePos.setFaPos(currentPos);}}}// 判斷終點是否在開啟列表中for (Position tpos : openList) {if (tpos.row == x2 && tpos.col == y2) {termPos = tpos;findFlag = true;break;}}} while (openList.size() != 0);if (!findFlag) {System.out.println("no valid path!");return;}Stack<String> resStack = new Stack<String>();String pattern = "(%d, %d)";if (termPos != null) {resStack.push(String.format(pattern, termPos.row, termPos.col));temp_x = termPos.row;temp_y = termPos.col;int temp_fangxiang = 0;while (termPos.fa != null) {termPos = termPos.fa;// System.out.println(termPos.row);// System.out.println(termPos.col);double value = Math.sqrt(Math.pow(Math.abs(termPos.row - temp_x), 2) + Math.pow(Math.abs(termPos.col - temp_y), 2));// System.out.println(value);result = result + Math.sqrt(Math.pow(Math.abs(termPos.row - temp_x), 2) + Math.pow(Math.abs(termPos.col - temp_y), 2));// System.out.println(result);temp_x=termPos.row;temp_y=termPos.col;resStack.push(String.format(pattern, termPos.row, termPos.col));}}StringBuilder sb = new StringBuilder();while (!resStack.empty()) {sb.append(resStack.pop());if (!resStack.empty()) {sb.append(" -> ");}}System.out.println(sb.toString());}/*** 計算某個格子的H值** @param x* @param y* @param tx 終點的x值* @param ty 終點的y值* @return*/private static int calcH(int x, int y, int tx, int ty) {//曼哈頓代價公式 預估代價int diff = Math.abs(x - tx) + Math.abs(y - ty);return diff * 10;}static class Position {public int F;public int G;public int H;public Position fa;public int row;public int col;public Position() {}public Position(int row, int col, int H) {this(row, col, H, null);}public Position(int row, int col, int H, Position pos) {this.H = H;this.row = row;this.col = col;this.fa = pos;this.G = calcG();this.F = G + H;}/*** 計算某個點到起始點的代價G** @return*/private int calcG() {if (fa == null) return 0;if (fa.row != this.row && fa.col != this.col) {return 14 + fa.G;}return 10 + fa.G;}public void setFaPos(Position pos) {this.fa = pos;this.G = calcG();this.F = G + H;}@Overridepublic boolean equals(Object obj) {if (obj == null) {return false;}if (!(obj instanceof Position)) {return false;}Position pos = (Position) obj;return this.row == pos.row && this.col == pos.col;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + row;result = prime * result + col;return result;}} }總結
- 上一篇: Scrapy框架之Spiders类理解
- 下一篇: server2003安装sqlserve