LOJ #6121. 「網絡流 24 題」孤島營救問題ios
一個 \(n \times m\) 的矩陣,每一個單元位置用一個有序數對(行號,列號)表示。數組
上下左右四個方向相鄰的兩個單元格之間存在一下狀況:網絡
直接相連函數
符合某種條件的狀況下相連測試
不相連優化
其中某種條件分爲 \(p\) 類要素,使一種條件成立的要素相同,不一樣條件成立的要素不一樣。spa
初始位置爲 \((1,1)\) ,問如何以最少步數到達 \((n,m)\) 。debug
數據範圍這麼友好,不暴力怎麼對得起出題人呢??/jkcode
考慮定義
一個四維數組表示 \((x_1,y_1) \to (x_2,y_2)\) 是否符合條件相連通。
\(vis[i][j][k]\) 表示條件要素爲 \(k\) 的狀況下,\((i,j)\) 位置是否已經查找過。
\(key[i][j]\) 表示第 \(key\) 類要素須要在 \((i,j)\) 單元獲取。
這裏用用到狀態壓縮存儲條件要素。(不會狀壓的請去睡覺)
而後,而後就能夠直接枚舉 \(DFS\) 了。(不會 \(DFS\) 搜最短路徑的請去睡覺)
定義結構體記錄單元(行號,列號,知足的條件,到該單元的最小花費),用隊列存儲(將路徑記錄下來),減小枚舉數量。
鑰匙質量不錯,不是一次性的woc
鑰匙作工不錯,一個單元能夠放多把鑰匙woc
初始點好像並無說不能放鑰匙woc
輸出 \(-1\) 贊~
\(DFS\) 不加 return
能夠卡掉五個測試點。。。(而後 \(debug\) 了一下午)
/* Name: #6121. 「網絡流 24 題」孤島營救問題 Solution: 最短路 By Frather_ */ #include <iostream> #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <vector> #include <set> // #include <map> #include <stack> #define ll long long #define InF 0x7fffffff #define kMax 10e5 #define kMin -10e5 #define kMod 998244353 #define kMod2 19260817 #define kMod3 19660813 #define base 1331 using namespace std; /*=========================================快讀*/ int read() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + (c ^ 48); c = getchar(); } return x * f; } /*=====================================定義變量*/ int n, m, p; int k; int s; int map[20][20][20][20], key[20][20]; struct node { int x, y; int key; int dis; }; bool vis[20][20][1 << 11]; queue<node> q; int dx[5] = {0, 1, -1, 0, 0}; int dy[5] = {0, 0, 0, 1, -1}; int ans = -1; /*===================================自定義函數*/ void bfs() { q.push((node){1, 1, 0 | key[0][0], 0}); //初始化第一個位置 vis[1][1][0 | key[1][1]] = true; while (!q.empty()) { node now = q.front(), next; q.pop(); for (int i = 1; i <= 4; i++) { next.x = now.x + dx[i]; next.y = now.y + dy[i]; if (next.x < 1 || next.x > n || next.y < 1 || next.y > m || !map[now.x][now.y][next.x][next.y]) //若dfs越界或者該兩單元間不存在可通路(即有「一堵不可逾越的牆」),跳過 continue; if ((map[now.x][now.y][next.x][next.y] == -1) || (now.key & map[now.x][now.y][next.x][next.y])) { if (!key[next.x][next.y]) next.key = now.key; else next.key = now.key | key[next.x][next.y]; if (vis[next.x][next.y][next.key]) continue; vis[next.x][next.y][next.key] = true; next.dis = now.dis + 1; q.push(next); if (next.x == n && next.y == m) { ans = next.dis; return; } } } } } /*=======================================主函數*/ int main() { n = read(); m = read(); p = read(); k = read(); memset(map, -1, sizeof(map)); for (int i = 1; i <= k; i++) { int x_1 = read(); int y_1 = read(); int x_2 = read(); int y_2 = read(); int g = read(); map[x_1][y_1][x_2][y_2] = g ? 1 << g - 1 : g; map[x_2][y_2][x_1][y_1] = map[x_1][y_1][x_2][y_2]; } s = read(); for (int i = 1; i <= s; i++) { int x = read(); int y = read(); int g = read(); key[x][y] |= 1 << g - 1; } bfs(); printf("%d\n", ans); return 0; }
感謝閱讀,留個點贊謝謝~