用二維數組表示地圖,若值爲 1 則表示有障礙物,若值爲 0 則表示能夠通行。ios
輸入: m*n 的二維數組,佈線起點座標,佈線終點座標。數組
輸出: 最短佈線距離以及對應的佈線路徑。this
從起點開始佈線,將起點標記爲 0 ,把四周可佈線的位置標記爲 起點標記值 + 1 ,同時將這些點插進隊列 Q (插到隊尾)。spa
從 Q 中取出一個點(隊首元素)重複佈線動做,將可佈線位置標記爲 取出點標記值 + 1 ,並插進 Q 。不斷重複上一個動做,直到找到終點,此時終點的標記值即最短佈線距離。code
爲何終點的標記值會等於最短佈線距離呢?blog
事實上對於每一點這個結論都是成立的(某點的標記值=該點到起點的最短距離)。隊列
(方塊表示起點,橢圓表示終點)it
在佈線的過程當中,始終遵循的規則是:標記值越小的越先佈線。(越先入隊的越先佈線)io
咱們假設對於標記值爲 n 的點該結論成立,咱們只須要證實從標記值爲 n 的點出發,找到的標記值爲 n+1 的點確實最短就能夠了。class
咱們考察標記值 n 周圍的可佈線點,能夠分爲兩類:已佈線點和未佈線點。
對於未佈線的點:由佈線規則可知,全部標記值 < n 點都已經佈線完畢,點未被佈線的惟一緣由是任何一個標記值 < n 的點都沒法與它相鄰(到不了或者須要付出更大的代價才能到),因此該點只能經過點 n 或者相鄰的標記值一樣爲 n 的點與起點聯通,從而取得最小值,故對標記值爲 n+1 的點結論一樣成立。
所以該結論對於任意標記值的點都成立。
#include <stdio.h> #include <cstdlib> #include <iostream> #include <queue> using namespace std; #define MAX 6 struct Point { int x; int y; int len; Point* pre; Point(): len(0), pre(0) {} Point(int x, int y): x(x), y(y), len(0), pre(0) {} void setPoint(int x, int y) { this->x = x; this->y = y; } }; queue<Point> mark; void test(Point (*p)[MAX]); bool work(Point& q, Point& e, int (*map)[MAX], Point (*p)[MAX]) { int x, y; // up if ((x=q.x-1) >= 0 && map[x][y=q.y] != 1 && p[x][y].len == 0) { p[x][y].len = q.len + 1; p[x][y].pre = &q; if (x == e.x && y == e.y) { return true; } else { mark.push(p[x][y]); } } // down if ((x=q.x+1) < MAX && map[x][y=q.y] != 1 && p[x][y].len == 0) { p[x][y].len = q.len + 1; p[x][y].pre = &q; if (x == e.x && y == e.y) { return true; } else { mark.push(p[x][y]); } } // left if ((y=q.y-1) >= 0 && map[x=q.x][y] != 1 && p[x][y].len == 0) { p[x][y].len = q.len + 1; p[x][y].pre = &q; if (x == e.x && y == e.y) { return true; } else { mark.push(p[x][y]); } } // right if ((y=q.y+1) < MAX && map[x=q.x][y] != 1 && p[x][y].len == 0) { p[x][y].len = q.len + 1; p[x][y].pre = &q; if (x == e.x && y == e.y) { return true; } else { mark.push(p[x][y]); } } return false; } void f(int (*map)[MAX], Point& s, Point& e, bool& k, Point (*p)[MAX]) { mark.push(s); int flag = false; while (mark.size() != 0 && !flag) { // 終止條件:找遍全部點都沒找到終點&找到終點 flag = work(mark.front(), e, map, p); mark.pop(); test(p); // 輸出佈線狀況 } k = flag; } void test(Point (*p)[MAX]) { // 輸出佈線狀況 for (int i = 0; i != MAX; ++i) { for (int j = 0; j != MAX; ++j) { printf("%d ", p[i][j].len); } cout << endl; } cout << endl; } void printPath(Point& end) { if (end.pre == 0) { printf("[%d][%d]\n", end.x, end.y); return; } else { printPath(*(end.pre)); printf("[%d][%d]\n", end.x, end.y); } } int main() { int map[MAX][MAX] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1 }; Point s(1, 1); Point e(4, 4); bool k = false; Point p[MAX][MAX]; p[s.x][s.y].len = 1; for (int i = 0; i != MAX; ++i) { for (int j = 0; j != MAX; ++j) { p[i][j].setPoint(i, j); } } // 初始化 f(map, s, e, k, p); if (k) { printf("MIN=%d\n", p[e.x][e.y].len); printPath(p[e.x][e.y]); } else { printf("ERROR\n"); // 起點與終點不連通 } return 0; }
上面那道題用隊列,這道用棧。
#include <stdio.h> #define MAX 7 struct Point { int x; int y; bool mark; Point(): x(0), y(0), mark(false) {} Point(int x, int y): x(x), y(y) {} void setPosition(int x, int y) { this->x = x; this->y = y; } }; Point p[MAX][MAX]; bool seekPath(int (*map)[MAX], Point& s, Point& e) { p[s.x][s.y].mark = true; if (s.x == e.x && s.y == e.y) { printf("MAP[%d][%d]\n", e.x, e.y); return true; } //printf("seekPath:1\n"); if (s.x+1 < MAX && map[s.x+1][s.y] != 1 && !p[s.x+1][s.y].mark && seekPath(map, p[s.x+1][s.y], e)) { printf("MAP[%d][%d]\n", s.x, s.y); return true; } //printf("seekPath:2\n"); if (s.x-1 >= 0 && map[s.x-1][s.y] != 1 && !p[s.x-1][s.y].mark && seekPath(map, p[s.x-1][s.y], e)) { printf("MAP[%d][%d]\n", s.x, s.y); return true; } //printf("seekPath:3\n"); if (s.y+1 < MAX && map[s.x][s.y+1] != 1 && !p[s.x][s.y+1].mark && seekPath(map, p[s.x][s.y+1], e)) { printf("MAP[%d][%d]\n", s.x, s.y); return true; } //printf("seekPath:4\n"); if (s.y-1 >= 0 && map[s.x][s.y-1] != 1 && !p[s.x][s.y-1].mark && seekPath(map, p[s.x][s.y-1], e)) { printf("MAP[%d][%d]\n", s.x, s.y); return true; } //printf("seekPath:5\n"); if (s.x+1 < MAX && s.y+1 < MAX && map[s.x+1][s.y+1] != 1 && !p[s.x+1][s.y+1].mark && seekPath(map, p[s.x+1][s.y+1], e)) { printf("MAP[%d][%d]\n", s.x, s.y); return true; } //printf("seekPath:6\n"); if (s.x+1 < MAX && s.y-1 >= 0 && map[s.x+1][s.y-1] != 1 && !p[s.x+1][s.y-1].mark && seekPath(map, p[s.x+1][s.y-1], e)) { printf("MAP[%d][%d]\n", s.x, s.y); return true; } //printf("seekPath:7\n"); if (s.x-1 >= 0 && s.y+1 < MAX && map[s.x-1][s.y+1] != 1 && !p[s.x-1][s.y+1].mark && seekPath(map, p[s.x-1][s.y+1], e)) { printf("MAP[%d][%d]\n", s.x, s.y); return true; } //printf("seekPath:8\n"); if (s.x-1 >= 0 && s.y-1 >= 0 && map[s.x-1][s.y-1] != 1 && !p[s.x-1][s.y-1].mark && seekPath(map, p[s.x-1][s.y-1], e)) { printf("MAP[%d][%d]\n", s.x, s.y); return true; } return false; } void f(int (*map)[MAX], Point& s, Point& e) { // chushihua for (int i = 0; i != MAX; ++i) { for (int j = 0; j != MAX; ++j) { p[i][j].setPosition(i, j); } } // work if (!seekPath(map, s, e)) { printf("ERROR!\n"); } //printf("f:runnable\n"); } int main() { int map[MAX][MAX] = { 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0 }; Point s(0, 0); Point e(2, 6); f(map, s, e); //printf("main:runnable\n"); return 0; }
留着備用。