問題:
在 n × n 方格的國際象棋棋盤上,馬(也稱為騎士Knight)從任意指定的方格出發,以跳馬規則(橫一步豎兩步或橫兩步豎一步),周游棋盤的每一個格子,要求每個格子只能跳過一次。
思路:
搜索部分就是普通的回溯
void KnightPatrol(int n, int count, step steps[], int map[][8]) {//n表示棋盤規模,count表示騎士已經走過的步數,steps記錄騎士巡游過的點,map用來標記地圖上每個點有沒被走過 if (count == n*n) {//如果騎士巡游過了所有的點 display(steps, n); } for (int i = N; i <= NW; i++) {//對每個方向遍歷 step then = overlook(steps[count], i);//向i方向眺望一下 bool lonely = false; if (count % 2 == 0) { lonely = hasLonelyPoint(map, n); } if (isInside(n, then) && !isOverlap(map, then) && !lonely) {//如果騎士下一步沒有跑到地圖外面,且沒有走到剛才走過的地方 //並且地圖中沒有走不到的點 patrol(steps, count, then, map); KnightPatrol(n, count + 1, steps, map); map[steps[count + 1].x][steps[count + 1].y] = 0; } } }
但是我這里設計了一個剪枝函數,具體思路就是每走一步,就判斷下地圖中是否有永遠不能被走到的點
就是因為這個棒棒噠剪枝函數,運行速度提高了不知道多少
bool hasLonelyPoint(int map[][8], int n) {//判斷地圖中是否有孤立的點,即怎么都走不到的點 step point1, point2; for (int i = 1; i <= n; i++) { for (int j = 1, count = 0; j <= n; j++) { if (map[i][j] == 0) { point1.x = i; point1.y = j; int count = 0; for (int k = N; k <= NW; k++) { point2 = overlook(point1, k); if (!isInside(n, point2)) count++;//point1 周圍的8個點中有點在地圖外 if (map[point2.x][point2.y] == 1) count++;//point1 周圍的8個點中有點被踩過 } if (count >= 8) return true;//如果8個方向全都不行,說明這個點永遠都無法被走到了 } } } return false; }