牛客多校2021(二)I.Penguins(BFS)
阿新 • • 發佈:2021-07-27
-
題目:Penguins
- 題意:給出兩張20 * 20的地圖,起點1為(20, 20),起點2為(20, 1),終點1為(1, 20),終點2為(1, 1),兩個企鵝需要分別從起點1->終點1、起點2->終點2,若企鵝1向上或向下走,企鵝2執行相同操作,若企鵝1向左或向右走,則企鵝2執行相反操作,求企鵝1到達終點1且企鵝同時到達終點2的最短路徑(若存在多條最短路徑,則輸出字典序最小的路徑),並將每次操作方向、以及走過的路徑輸出(將這兩張圖輸出即可,只需要將走過的路徑標記為'A')。
- 解析:這道題思路很顯然用廣搜,首先需要開一個四維陣列(或結構體)記錄兩個企鵝的位置,按照"D、L、R、U"的順序進行廣搜, 每次搜到下一個結點位置則記錄其上一個結點位置,並記錄到下一個結點
ps:若其中一隻企鵝下一個結點無法到達(碰牆、碰障礙)則需要讓其回到原來位置(或者說是原地不動),另一隻企鵝可以繼續其操作。 - 程式碼:
#include<iostream> #include<cstdio> #include<queue> #include<string.h> #include<algorithm> using namespace std; const int N = 25; char g1[N][N], g2[N][N]; int dir[4][2] = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}}; int step = 0; char op[10] = {'D', 'L', 'R', 'U'}; char p[N][N][N][N]; //記錄該位置 char path[10005]; struct Node { int x1, y1, x2, y2; }; Node pre_node[N][N][N][N]; //該位置上一個點的位置 int dis[N][N][N][N]; bool check1(int x, int y) { if(g1[x][y] == '#' || x < 1 || x > 20 || y < 1 || y > 20) return true; return false; } bool check2(int x, int y) { if(g2[x][y] == '#' || x < 1 || x > 20 || y < 1 || y > 20) return true; return false; } void bfs() { queue<Node> q; q.push({20, 20, 20, 1}); dis[20][20][20][1] = 0; while(q.size()) { Node t = q.front(); q.pop(); if(t.x1 == 1 && t.y1 == 20 && t.x2 == 1 && t.y2 == 1) return; for(int i = 0; i < 4; i++) { int xx1 = t.x1 + dir[i][0], yy1 = t.y1 + dir[i][1]; if(check1(xx1, yy1)) //碰牆或者遇到障礙 { xx1 -= dir[i][0]; yy1 -= dir[i][1]; } int xx2 = t.x2 + dir[i][0], yy2 = t.y2 - dir[i][1]; //xx2座標與xx1座標變換相同但yy2需要與yy1操作相反 if(check2(xx2, yy2)) //碰牆或者遇到障礙 { xx2 -= dir[i][0]; yy2 += dir[i][1]; } if(dis[xx1][yy1][xx2][yy2] == -1) //之前未訪問過(保證是最短路徑) { pre_node[xx1][yy1][xx2][yy2] = {t.x1, t.y1, t.x2, t.y2}; dis[xx1][yy1][xx2][yy2] = dis[t.x1][t.y1][t.x2][t.y2] + 1; //記錄當前路徑長度 p[xx1][yy1][xx2][yy2] = op[i]; //記錄方向 q.push({xx1, yy1, xx2, yy2}); } } } } void find_Path(int x1, int y1, int x2, int y2) { g1[x1][y1] = 'A', g2[x2][y2] = 'A'; if(x1 == 20 && y1 == 20 && x2 == 20 && y2 == 1) return; int xx1 = pre_node[x1][y1][x2][y2].x1; int yy1 = pre_node[x1][y1][x2][y2].y1; int xx2 = pre_node[x1][y1][x2][y2].x2; int yy2 = pre_node[x1][y1][x2][y2].y2; find_Path(xx1, yy1, xx2, yy2); path[step++] = p[x1][y1][x2][y2]; } int main() { memset(dis, -1, sizeof dis); for(int i = 1; i <= 20; i++) scanf("%s%s", g1[i] + 1, g2[i] + 1); bfs(); find_Path(1, 20, 1, 1); //從終點遞迴尋找路徑 printf("%d\n%s\n", step, path); for(int i = 1; i <= 20; i++) printf("%s %s\n", g1[i] + 1, g2[i] + 1); return 0; }