使用BFS,在二維地圖中,尋求特定走法的最短距離。
這個問題,是我從USACO Camelot問題中,抽出的一個小問題,比較典型。
在一個二維地圖中,給定一個初始點,和相應的行走規則,求從這個初始點可到達的點的最小步數。
舉個例子:(camelot問題中,knight的走法)
給出行走規則:
如圖,行走規則共有8個,及從圖中的黑點到白點的8個行走路線,當然,在行走時,不能躍出地圖的邊界。
地圖大小,這裡假定為5*5的。
初始點,即為中間的那個黑點。
基本思想,及使用BFS,每次的層擴充套件,都將新增從此點(使用8個規則)可到達的點。
每一層都比上一層的距離 加一。
如上圖,這是一種假設的情形,從起始點開始,第一層只有4個點滿足(可到達條件,未出界條件,未被訪問條件(及沒進過佇列))。然後第二層依次的可達點可能會有3個,1個,0個(假設的示意圖),依次往下,直到佇列為空。
下面給出一個具體的形式化例子。
輸入定義:
兩行:第一行代表行和列,第二行代表起始點的座標
其中,行和列的編號從數字1開始
(例如)
8 8
4 4
輸出定義:
從行1,列1開始依次按先行後列的順序遞加。可達測輸出相應的距離,不可達則輸出N,中間以空格間隔,.到每行的末尾輸出換行。(規定,點到自身也為不可達,這僅為程式設計時好處理而已,及初始化時距離統一賦值為0,當bfs過程完後,仍為0及表示不可達)
(例如,當使用如上輸入,和規則 --- knight的走法)
2 3 2 3 2 3 2 3
3 4 1 2 1 4 3 2
2 1 2 3 2 1 2 3
3 2 3 N 3 2 3 2
2 1 2 3 2 1 2 3
3 4 1 2 1 4 3 2
2 3 2 3 2 3 2 3
3 2 3 2 3 2 3 4
下面是C語言實現程式碼
#include<stdio.h> #include<string.h> #include<stdlib.h> #define MAXX 20 #define MAXY 20 //在這裡定義規則 int dx[8]= {2,2,1,1,-2,-2,-1,-1}; int dy[8]= {-1,1,-2,2,-1,1,-2,2}; //第二個規則 //int dx[1] = {1}; //int dy[1] = {1}; int visit[MAXX][MAXY]; long d[MAXX][MAXY][MAXX][MAXY]; int m,n; void bfsPath(int sx,int sy) { int q[2][1000]; int head, tail, i, tx, ty; memset(q, 0, sizeof(q)); memset(visit, 0, sizeof(visit)); head = 0; tail = 1; q[0][tail] = sx; q[1][tail] = sy; visit[sx][sy] = 1; while ( head<tail ) { head++; tx = q[0][head]; ty = q[1][head]; for (i=0; i<8; i++) //every level 當規則改變是,每次深搜的邊界值要變,如使用第二個規則,8 要變為 1 if( tx+dx[i]>=1 && tx+dx[i]<=n && ty+dy[i]>=1 && ty+dy[i]<=m && !visit[tx+dx[i]][ty+dy[i]]) { //put into the queue tail++; q[0][tail] = tx+dx[i]; q[1][tail] = ty+dy[i]; //mark visit[tx+dx[i]][ty+dy[i]] = 1; d[sx][sy][q[0][tail]][q[1][tail]] = d[sx][sy][tx][ty] + 1; } } } int main(void) { int startX, startY; int i, j; scanf("%d %d", &n, &m); scanf("%d %d", &startX, &startY); memset(d, 0, sizeof(d)); bfsPath(startX, startY); for (i=1; i<=n; i++){ for (j=1; j<=m; j++) { if (d[startX][startY][i][j] == 0) printf("N "); else printf("%d ", d[startX][startY][i][j]); } printf("\n"); } return 0; }</span>
在舉例中,knight的走法可以訪問每一個點(自身除外),但有些規則是不能訪問到每個點的。
下面將規則變為 只能按(+1,+1)的規則走:
輸入:
8 8
4 4
輸出:
N N N N N N N N
N N N N N N N N
N N N N N N N N
N N N N N N N N
N N N N 1 N N N
N N N N N 2 N N
N N N N N N 3 N
N N N N N N N 4