算法其實很簡單—馬踏棋盤算法(騎士周遊)

目錄

1.馬踏棋盤算法介紹和遊戲演示

2.馬踏棋盤遊戲代碼實現

3.騎士周遊問題的解決步驟和思路

4.代碼優化

5.代碼實現


1.馬踏棋盤算法介紹和遊戲演示

1)馬踏棋盤算法也被稱爲騎士周遊問題

2)將馬隨機放在國際象棋的8X8棋盤Board[0~ 7][0~7]的某個方格中,馬按走棋規則(馬走日字)進行移動。要求每個方格只進入一次,走遍棋盤上全部64個方格

3) 遊戲演示:http://www.4399.com/flash/146267_2.htm

 

2.馬踏棋盤遊戲代碼實現

1)馬踏棋盤問題(騎士周遊問題)實際上是圖的深度,優先搜索(DFS)的應用。

2)如果使用回溯(就是深度優先搜索)來解決,假如馬兒踏了53個點,如圖:走到了第53個,座標(1,0) ,發現已經走到盡頭,沒辦法,那就只能回退了,查看其他的路徑,就在棋盤.上不停的回溯

3) 分析第一種方式的問題,並使用貪心算法( greedyalgorithm)進行優化。解決馬踏棋盤問題.

4)使用前面的遊戲來驗證算法是否正確。

3.騎士周遊問題的解決步驟和思路

1.創建棋盤chessBoard,是一個二維數組

2.將當前位置設置爲已經訪問,然後根據當前位置,計算馬兒還能走哪些位置,並放入到一個集合中(ArrayList),最多有8個位置,每走一步, 就使用step+1

3.遍歷ArrayList中存放的所有位置,看看哪個可以走通,如果走通,就繼續,走不通,就回溯

4.判斷馬兒是否完成了任務,使用step 和應該走的步數比較,如果沒有達到數量,則表示沒有完成任務,將整個棋盤置0

注意:馬兒不同的走法(策略),會得到不同的結果,效率也會有影響(優化)

4.代碼優化

使用該代碼,我本地沒有跑出結果,一直在運行,所以對代碼進行下一步優化。

等了好久都木有結果:

 

由於馬兒的不同走法會有不同的策略,如果回溯的話,是比較影響性能的,所有,我們在對馬兒走下一步選擇的點可以進行優化。

我們可以算出馬兒選擇走下一步的下一步有幾種選擇,使用貪心算法,算出最少選擇進行下一步,下一步的下一步選擇越少,則回溯所消耗的性能越少,所以,我們可以對下一步集合中的點進行排序,選出選擇最少的。

優化前沒有跑出結果,但是優化後:

 

通過結果玩遊戲,完美win,但是不一定每次都能回到原點:

 

5.代碼實現

package com.example.datastructureandalgorithm.horse;

import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;

/**
 * 馬踏棋盤算法
 *
 * @author 浪子傑
 * @version 1.0
 * @date 2020/6/27
 */
public class HorseChessDemo {
    /**
     * 棋盤的行數
     */
    private static int X;
    /**
     * 棋盤的列數
     */
    private static int Y;

    /**
     * 標記棋盤各個位置是否被訪問
     */
    private static boolean visited[];

    /**
     * 判斷是否成功
     */
    private static boolean isFinished;

    public static void main(String[] args) {
        System.out.println("騎士開始周遊啦...");
        X = 6;
        Y = 6;
        // 初始位置行數
        int row = 1;
        // 初始位置列數
        int column = 2;
        // 創建棋盤
        int[][] chessboard = new int[X][Y];
        visited = new boolean[X * Y];
        // 耗時
        long start = System.currentTimeMillis();
        traversalChess(chessboard, row - 1, column - 1, 1);
        long end = System.currentTimeMillis();
        System.out.println("總共耗時:" + (end - start) + "毫秒");
        for (int[] rows : chessboard) {
            for (int step : rows) {
                System.out.print(step + "\t");
            }
            System.out.println();
        }
    }

    public static void traversalChess(int[][] chessboard, int row, int column, int step) {
        chessboard[row][column] = step;
        // row * X + column表示被訪問節點的位置,即從0開始數
        visited[row * X + column] = true;
        // 獲取下一步可以走的位置的集合
        ArrayList<Point> arrayList = next(new Point(column, row));
        // 排序
        sort(arrayList);
        while (!arrayList.isEmpty()) {
            Point point = arrayList.remove(0);
            // 判斷是否被訪問過
            if (!visited[point.y * X + point.x]) {
                // 記得step+1,表示一共走的步數
                traversalChess(chessboard, point.y, point.x, step + 1);
            }
        }
        // 判斷馬兒是否完成了任務,使用step和棋盤總步數進行比較
        // 如果沒有完成,則將棋盤還原
        if (step < X * Y && !isFinished) {
            chessboard[row][column] = 0;
            visited[row * X + column] = false;
        } else {
            isFinished = true;
        }
    }

    /**
     * 根據當前的位置,計算馬兒還可以走哪些位置,並放入list中,list最大爲8
     *
     * @param point
     * @return
     */
    public static ArrayList<Point> next(Point point) {
        ArrayList<Point> arrayList = new ArrayList<>();
        Point p1 = new Point();
        // 表示馬兒可以走上圖中的位置1
        if ((p1.x = point.x - 1) >= 0 && (p1.y = point.y - 2) >= 0) {
            arrayList.add(new Point(p1));
        }
        // 表示馬兒可以走上圖中的位置2
        if ((p1.x = point.x + 1) < X && (p1.y = point.y - 2) >= 0) {
            arrayList.add(new Point(p1));
        }
        // 表示馬兒可以走上圖中的位置3
        if ((p1.x = point.x + 2) < X && (p1.y = point.y - 1) >= 0) {
            arrayList.add(new Point(p1));
        }
        // 表示馬兒可以走上圖中的位置4
        if ((p1.x = point.x + 2) < X && (p1.y = point.y + 1) < Y) {
            arrayList.add(new Point(p1));
        }
        // 表示馬兒可以走上圖中的位置5
        if ((p1.x = point.x + 1) < X && (p1.y = point.y + 2) < Y) {
            arrayList.add(new Point(p1));
        }
        // 表示馬兒可以走上圖中的位置6
        if ((p1.x = point.x - 1) >= 0 && (p1.y = point.y + 2) < Y) {
            arrayList.add(new Point(p1));
        }
        // 表示馬兒可以走上圖中的位置7
        if ((p1.x = point.x - 2) >= 0 && (p1.y = point.y + 1) < Y) {
            arrayList.add(new Point(p1));
        }
        // 表示馬兒可以走上圖中的位置8
        if ((p1.x = point.x - 2) >= 0 && (p1.y = point.y - 1) >= 0) {
            arrayList.add(new Point(p1));
        }
        return arrayList;
    }

    /**
     * 對list進行排序
     * @param arrayList
     */
    public static void sort(ArrayList<Point> arrayList) {
        arrayList.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                int count1 = next(o1).size();
                int count2 = next(o2).size();
                return count1 - count2;
            }
        });
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章