计蒜客题解——T1213:拯救行动
題目相關
題目鏈接
計蒜客 OJ,https://nanti.jisuanke.com/t/T1213。
題目描述
公主被惡人抓走,被關押在牢房的某個地方。牢房用 N×M(N,M≤200) 的矩陣來表示。矩陣中的每項可以代表道路(@)、墻壁(#)、和守衛(x)。
英勇的騎士(r)決定孤身一人去拯救公主(a)。我們假設拯救成功的表示是 "騎士到達了公主所在的位置"。由于在通往公主所在位置的道路中可能遇到守衛,騎士一旦遇到守衛,必須殺死守衛才能繼續前進。
現假設騎士可以向上、下、左、右四個方向移動,每移動一個位置需要 1 個單位時間,殺死一個守衛需要花費額外的 1 個單位時間。同時假設騎士足夠強壯,有能力殺死所有的守衛。
給定牢房矩陣,公主、騎士和守衛在矩陣中的位置,請你計算拯救行動成功需要花費最短時間。
輸入格式
1、兩個整數代表 N 和 M,(N,M≤200).
2、隨后 N 行,每行有 M 個字符。"@" 代表道路,"a" 代表公主,"r" 代表騎士,"x" 代表守衛, "#" 代表墻壁。
輸出格式
如果拯救行動成功,輸出一個整數,表示行動的最短時間。
如果不可能成功,輸出 "Impossible"。
樣例輸入1
7 8 #@#####@ #@a#@@r@ #@@#x@@@ @@#@@#@# #@@@##@@ @#@@@@@@ @@@@@@@@樣例輸出1
13樣例輸入2
13 40 @x@@##x@#x@x#xxxx##@#x@x@@#x#@#x#@@x@#@x xx###x@x#@@##xx@@@#@x@@#x@xxx@@#x@#x@@x@ #@x#@x#x#@@##@@x#@xx#xxx@@x##@@@#@x@@x@x @##x@@@x#xx#@@#xxxx#@@x@x@#@x@@@x@#@#x@# @#xxxxx##@@x##x@xxx@@#x@x####@@@x#x##@#@ #xxx#@#x##xxxx@@#xx@@@x@xxx#@#xxx@x##### #x@xxxx#@x@@@@##@x#xx#xxx@#xx#@#####x#@x xx##@#@x##x##x#@x#@a#xx@##@#@##xx@#@@x@x x#x#@x@#x#@##@xrx@x#xxxx@##x##xx#@#x@xx@ #x@@#@###x##x@x#@@#@@x@x@@xx@@@@##@@x@@x x#xx@x###@xxx#@#x#@@###@#@##@x#@x@#@@#@@ #@#x@x#x#x###@x@@xxx####x@x##@x####xx#@x #x#@x#x######@@#x@#xxxx#xx@@@#xx#x#####@樣例輸出2
7題目分析
題意分析
一個 N*M 大小的迷宮,我們從 r 位置出發(也就是起點),字符 @ 表示可以安全通行的方格,字符 # 表示墻壁(也就是不能走),字符 x 代表守衛(守衛可以殺死,但是必須付出額外的 1 個單位時間),字符 a 表示仙藥(也就是終點)。要求輸出從 @ 到 a 的最短路徑。那么迷宮問題的基本要素全齊了,所以本題就是一道 BFS 模板題。
樣例數據分析
本題和以前的 BFS 模板題唯一的不同就是所有守衛可以殺死,但是需要付出額外的時間。因此意味著 x 的地方是可以走的,只是要多付出 1 個單位時間。也就是說,走 x 地方,需要 2 個時間單位;走 @ 地方,需要 1 個時間單位。
省略。如果想看類似的數據分析,可以看以前的文章,https://blog.csdn.net/justidle/article/details/104651311。主要是我偷懶了,畫圖太累了,請原諒。
算法思路
1、讀入數據,并寫入到合適的數據結構中。
2、找到起點位置,將起點加入到隊列 q 中。
3、記錄終點位置信息。
4、開始 BFS 遍歷。直到找到終點或者遍歷所有節點而無法到達終點。注意:走 x 地方,需要 2 個時間單位;走 @ 地方,需要 1 個時間單位。
AC 參考代碼
#include <cstdio> #include <queue>//位置定義 struct POS {int x, y;//坐標int cost;//本節點到起點的距離 };const int MAXN = 202; struct MAZE {int row, col;//迷宮大小char data[MAXN][MAXN];//迷宮數據描述bool visit[MAXN][MAXN];//是否已經訪問過節點int x1, y1;//起點坐標int x2, y2;//終點坐標 };int bfs(MAZE &maze);int main() {MAZE maze = {};//迷宮定義并將所有初始化為零//讀入迷宮長寬 scanf("%d %d", &maze.row, &maze.col);//讀入迷宮數據int i,j;for (i=0; i<maze.row; i++) {for (j=0; j<maze.col; j++) {scanf(" %c", &maze.data[i][j]);if (maze.data[i][j]=='a') {//終點maze.x2 = i;maze.y2 = j; } else if (maze.data[i][j]=='r') {//起點maze.x1 = i;maze.y1 = j; }}} int ans = bfs(maze);if (ans>0) {printf("%d\n", ans);} else {printf("Impossible\n");}return 0; }int bfs(MAZE &maze) {std::queue<POS> q;//下一個節點隊列const POS move[] = {{-1,0}, {0,1}, {1,0}, {0,-1}};//騎士的移動方法POS cur;//當前位置POS next;//下一個位置//加入起點cur.x = maze.x1;cur.y = maze.y1;cur.cost = 0;maze.visit[cur.x][cur.y] = true;//設置本節點已經訪問q.push(cur); //開始遍歷while (!q.empty()) {//彈出隊首節點cur = q.front();q.pop();if (maze.data[cur.x][cur.y]=='x') {//由于有干掉守衛,所以我們我們先加入的不一定是最小的maze.data[cur.x][cur.y]='@';cur.cost++;q.push(cur);} else {for (int i=0; i<4; i++) {next.x = cur.x + move[i].x;next.y = cur.y + move[i].y;//判斷是不是終點if (next.x==maze.x2 && next.y==maze.y2) {return cur.cost + 1;} //判斷通過性if (next.x>=0&&next.x<maze.row&&next.y>=0&&next.y<maze.col&&maze.visit[next.x][next.y]==false&&maze.data[next.x][next.y]!='#') {next.cost = cur.cost + 1;maze.visit[next.x][next.y] = true;q.push(next);}}}}return -1; }代碼分析
1、如何表示一個節點的坐標,以及該節點到起點的距離。這里我用一個自定義的結構體來表示。如下所示:
struct POS {int x, y;//當前結點坐標int cost;//從起點到當前結點的距離 };2、如何表示一個迷宮。這里我將所有迷宮信息全部放在一個自定義結構體中,增強了代碼可讀性。如下所示:
const int MAXN = 200; struct MAZE {int m, n;//迷宮大小char data[MAXN][MAXN];//迷宮的數據bool visit[MAXN][MAXN];//是否已經走過int x1, y1;//起點信息int x2, y2;//終點信息 };3、如何表示所有移動可能性。如下所示:
const POS move[] = {{-1,0}, {0,1}, {1,0}, {0,-1}};//定義移動方法4、新節點通過性判斷問題。根據題目進行判斷,基本包括以下幾個方面:
(1)這個位置可以走,如本題中用字符 . 表示。如下所示:
maze.data[next.x][next.y]!='#'注意,只要不是 # 就認為這個節點是可以走的。至于是否是守衛,我們等彈出的時候再判斷。這個細節是和標準走迷宮不一樣的。
(2)這個位置沒有訪問過。如下所示:
maze.visit[next.x][next.y]==false(3)這個位置處于迷宮內。這個判斷和您程序對迷宮定義有關。如下所示:
next.x>=0&&next.x<maze.m&&next.y>=0&&next.y<maze.n(4)判斷這個位置是不是守衛。在彈出隊首元素的時候才判斷。如下所示:
if (maze.data[cur.x][cur.y]=='x') {//由于有干掉守衛,所以我們我們先加入的不一定是最小的maze.data[cur.x][cur.y]='@';cur.cost++;q.push(cur); }當然,也可以在走到本位置的時候進行判斷。不管在哪里判斷,是不會影響結果的,這是由于 BFS 的特性決定的。
總結
以上是生活随笔為你收集整理的计蒜客题解——T1213:拯救行动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习~模糊神经网络(FNN)
- 下一篇: SKR!虎扑66万JRS大战3300万吴