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; }
感谢阅读,留个点赞谢谢~