牛客多校第二場 I.Penguins
阿新 • • 發佈:2021-07-20
題意
兩個企鵝,一個從地圖的右下角走右上角,一個從另一個地圖的左下角走到左上角,我們操控左邊的企鵝,右邊的企鵝與左邊企鵝運動規則如下。
- 左邊企鵝向左,右邊企鵝向右
- 左邊企鵝向右,右邊企鵝向左
- 左邊企鵝向上,右邊企鵝向上
- 左邊企鵝向下,右邊企鵝向下
與此同時,如果左右企鵝遇到了障礙,或者遇到了越界情況,那麼這一步就作廢。
求最小步數,並且給出字典序最小的方向變化,以及用\('A'\)來體現運動路徑。
解題:
說實話真的沒見過\(bfs\)還能這樣玩的,假設只有一隻企鵝那麼設狀態就\(d[x][y]\),那麼兩隻企鵝就是\(d[x1][y1][x2][y2]\)就好了呀,剩下的就是正常的\(bfs\)
g
陣列記錄就行。
細節:
- 要求輸出方向字典序最小,那麼就是輪詢的方向就是下、左、右、上了。
- 對於切換方向,如果1異或3等於2,2異或3等於1,很巧妙。
- 處理輸入,題目直接給了這樣一個輸入,兩個地圖用空格隔開,我可能直接用字元陣列一次性儲存兩個了,處理起來肯定賊麻煩。
但是可以這樣,直接儲存兩個地圖。
#include <bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int N = 20; #define x first #define y second string a[N], b[N]; int d[N][N][N][N]; int dx[4] = {1, 0, 0, -1}, dy[4] = {0, -1, 1, 0}; struct node { int x1, y1, x2, y2, i; }rem[N][N][N][N]; int another(int i) { if (i == 1 || i == 2) return i ^ 3; else return i; } PII move(string g[], int x, int y, int i) { int xx = x + dx[i], yy = y + dy[i]; if (xx < 0 || xx >= N || yy < 0 || yy >= N || g[xx][yy] == '#') return {x, y}; return {xx, yy}; } void bfs() { memset(d, -1, sizeof d); queue<node> q; q.push({N - 1, N - 1, N - 1, 0}); d[N - 1][N - 1][N - 1][0] = 0; while (q.size()) { auto t = q.front(); q.pop(); for (int i = 0; i < 4; i++) { PII leftP = move(a, t.x1, t.y1, i); PII rightP = move(b, t.x2, t.y2, another(i)); if (d[leftP.x][leftP.y][rightP.x][rightP.y] == -1) { d[leftP.x][leftP.y][rightP.x][rightP.y] = d[t.x1][t.y1][t.x2][t.y2] + 1; rem[leftP.x][leftP.y][rightP.x][rightP.y] = {t.x1, t.y1, t.x2, t.y2, i}; q.push({leftP.x, leftP.y, rightP.x, rightP.y}); } } } } int main() { string a[N], b[N]; for (int i = 0; i < N; i++) cin >> a[i] >> b[i]; bfs(); cout << d[0][N - 1][0][0] << endl; int ex1 = 0, ey1 = N - 1, ex2 = 0, ey2 = 0; string res = ""; while (true) { a[ex1][ey1] = b[ex2][ey2] = 'A'; if (ex1 == N - 1 && ey1 == N - 1 && ex2 == N - 1 && ey2 == 0) break; auto t = rem[ex1][ey1][ex2][ey2]; int x1 = t.x1, y1 = t.y1, x2 = t.x2, y2 = t.y2, i = t.i; string dir = "DLRU"; res += dir[i]; ex1 = x1, ey1 = y1, ex2 = x2, ey2 = y2; } reverse(res.begin(), res.end()); cout << res << endl; for (int i = 0; i < N; i++) { cout << a[i] << " " << b[i] << endl; } return 0; }