日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Problem - 6111迷宫出逃

發布時間:2024/4/18 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Problem - 6111迷宫出逃 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Problem Description

小明又一次陷入了大魔王的迷宮,在無人機的幫忙下,小明獲得了整個迷宮的草圖。不同于一般的迷宮,魔王在迷宮里安置了機關,一旦觸碰,那么四個方向所在的格子,將翻轉其可達性(原先可通過的格子不可通過,反之亦然,機關可以反復觸發)。為了防止小明很容易地出逃,魔王在臨走前把鑰匙丟在了迷宮某處,只有拿到鑰匙,小明才能開門在出口處離開迷宮。萬般無奈之下,小明想借助聰明的你,幫忙計算是否有機會離開這個迷宮,最少需要多少時間。(每一單位時間只能向四鄰方向走一步)

Input

第一行為 T,表示輸入數據組數。下面 T 組數據,對于每組數據:第一行是兩個數字 n, m(2 < n * m <= 64),表示迷宮的長與寬。接下來 n 行,每行 m 個字符,‘.’表示空地可以通過,‘x’表示陷阱,‘*’表示機關,‘S’代表起點,‘E’代表出口,‘K’表示鑰匙(保證存在且只有一個)。

Output

對第 i 組數據,輸出Case #i:然后輸出一行,僅包含一個整數,表示最少多少步能夠拿到鑰匙并走出迷魂陣,如果不能則打出-1。

Sample Input

5 5 7 ...*x.. ...x... xEx.... *x...K. .x*...S 5 7 K..*x.. ...x... xEx.... *x..... .x*...S 5 7 ..K*x.. ..*x*.. xEx.... *x..... .x*...S 5 7 ..K*x.. .*xx*.. *E*.... xx..... .x*...S 4 4 S*.. **.. ...E ...K

Sample Output

Case #1: 11 Case #2: 13 Case #3: 13 Case #4: 11 Case #5: -1

AC

  • 這道題有機關這個設定,可以用01表示每個位置是否翻轉,剛好地圖的大小最多是64,可以用一個unsigned long long表示,因為是求最少的步數所以BFS,剩下的就是判重,剛開始不會,看了網上的博客,都是用hash判重,感覺沒必要用hash,完全可以用set和map,當然這里需要注意,判重的結構體里面不應該存在步數(MLE),只要是這個狀態存在就跳過
  • 讀入數據的時候記錄起點,key,終點的位置
  • bfs搜索,發現一個新的狀態,就加入queue和set中,直到找到終點且此時鑰匙已經找到
// set #include <iostream> #include <stdio.h> #include <map> #include <vector> #include <set> #include <queue> #include <cstring> #include <cmath> #include <algorithm> #define N 100005 #define ll unsigned long long using namespace std; char a[70][70]; int kx, ky, ex, ey, sx, sy, n, m, ans; struct ac{int x, y, step;ll pos;bool key;// set排序 需要指定規則bool operator <(const ac &a) const{if (a.x != x) return a.x < x;else if (a.y != y) return a.y < y;// else if (a.step != step) return a.step < step;else if (a.pos != pos) return a.pos < pos;else return a.key < key;} }; int dx[4] = {0, 0, 1, -1}; int dy[4] = {1, -1, 0, 0}; set<ac> st; queue<ac> que; bool judge(int x, int y) {if (x < 0 || y < 0 || x >= n || y >= m)return false;return true; } void add(int x, int y, int step, ll pos, bool key) {ac t;t.x = x;t.y = y;t.pos = pos;t.key = key;// 當前狀態是否已經記錄if (st.find(t) != st.end()) {return;}st.insert(t);t.step = step;que.push(t); } // 觸發機關后改變四個方向的狀態 ll change(ll x, ll y, ll pos) {for (int i = 0; i < 4; ++i) {ll xx = x + dx[i];ll yy = y + dy[i];if (!judge(xx, yy)) continue;pos ^= 1ll << (xx * m + yy);}return pos; } void update(int x, int y, int step, ll pos, bool key) {if (!judge(x, y)) return;// 判斷當前位置是否翻轉bool flag = 1ll << (x * m + y) & pos;// 如果翻轉過而且原來是陷阱,現在就可以通過if (flag == true && a[x][y] == 'x') {// 加入隊列和setadd(x, y, step, pos, key);}// 如果沒有翻轉過,只要不是陷阱,就可以通過if (flag == false && a[x][y] != 'x') {if (x == kx && y == ky) {add(x, y, step, pos, true);}else if (a[x][y] == '*') {// 觸發機關改變四個方向的狀態add(x, y, step, change(x, y, pos), key);}else {add(x, y, step, pos, key);}} }void bfs() {ac t;t.x = sx;t.y = sy;t.pos = 0;t.key = false;// 清空set和queuewhile (!que.empty()) que.pop();st.clear();// set中沒有stepst.insert(t);t.step = 0;que.push(t);while (!que.empty()) {ac f = que.front();que.pop();// 如果找到鑰匙和出口,returnif (f.x == ex && f.y == ey && f.key) {ans = f.step;return;}// 向四個方向更新for (int i = 0; i < 4; ++i) {int x = f.x + dx[i];int y = f.y + dy[i];update(x, y, f.step + 1, f.pos, f.key);}} }int main() { #ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin); #endifint t;int Case = 1;scanf("%d", &t);while (t--) {scanf("%d%d", &n, &m);for (int i = 0; i < n; ++i) {scanf("%s", a[i]);}// 讀入數據,記錄for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {if (a[i][j] == 'K') {kx = i;ky = j;a[i][j] = '.';}if (a[i][j] == 'S') {sx = i;sy = j;a[i][j] = '.';}if (a[i][j] == 'E') {ex = i;ey = j;a[i][j] = '.';}}}ans = -1;bfs();printf("Case #%d:\n%d\n", Case++, ans);}return 0; } // hash #include <iostream> #include <stdio.h> #include <map> #include <vector> #include <set> #include <queue> #include <cstring> #include <cmath> #include <algorithm> #define N 10005 #define ll unsigned long long using namespace std;char a[64][64]; int sx, sy, kx, ky, ex, ey; int n, m; int ans; int mod = 10000; int dx[4] = {0, 0, 1, -1}; int dy[4] = {1, -1, 0, 0}; bool judge(int x, int y) {if (x < 0 || y < 0 || x >= n || y >= m)return false;elsereturn true; } struct ac{int x, y, step;ll pos;bool key;int hash() {return (pos % mod + x + y + key) % mod;}bool operator ==(const ac & t) {return t.x == x && t.y == y && pos == t.pos && key == t.key;} }; queue<ac> que; vector<ac> Hash[N]; void add(int x, int y, int step, bool key, ll pos) {ac t;t.x = x, t.y = y, t.step = step, t.key = key, t.pos = pos;int idx = t.hash();for (int i = 0; i < Hash[idx].size(); ++i) {if (Hash[idx][i] == t)return;}Hash[idx].push_back(t);que.push(t); } ll change(int x, int y, ll pos) {for (int i = 0; i < 4; ++i) {int xx = x + dx[i];int yy = y + dy[i];if (judge(xx, yy) == false) continue;pos ^= 1ll << (xx * m + yy);}return pos; } void update (int x, int y, int step, bool key, ll pos) {bool flag = (1ll << (x * m + y)) & pos;if (a[x][y] == 'x' && flag) {add(x, y, step, key, pos);}else if (a[x][y] != 'x' && flag == false) {if (x == kx && y == ky)add(x, y, step, true, pos);else if (a[x][y] == '*')add(x, y, step, key, change(x, y, pos));elseadd(x, y, step, key, pos);} }void bfs() {while (!que.empty()) que.pop();for (int i = 0; i < mod; ++i) {Hash[i].clear();}ac t;t.x = sx, t.y = sy, t.step = 0, t.key = false, t.pos = 0;Hash[t.hash()].push_back(t);que.push(t);while (!que.empty()) {ac f = que.front();que.pop();if (f.x == ex && f.y == ey && f.key == true) {ans = f.step;return;}for (int i = 0; i < 4; ++i) {int x = f.x + dx[i];int y = f.y + dy[i];if (judge(x, y) == false) continue;update(x, y, f.step + 1, f.key, f.pos);}} } int main() { #ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin); #endifint t, Case = 1;scanf("%d", &t);while (t--) {scanf("%d%d", &n, &m);for (int i = 0; i < n; ++i) {scanf("%s", a[i]);}for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {if (a[i][j] == 'K') {kx = i, ky = j;a[i][j] = '.';}if (a[i][j] == 'E') {ex = i, ey = j;a[i][j] = '.';}if (a[i][j] == 'S') {sx = i, sy = j;a[i][j] = '.';}}}ans = -1;bfs();printf("Case #%d:\n%d\n", Case++, ans);}return 0; }

總結

以上是生活随笔為你收集整理的Problem - 6111迷宫出逃的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。