国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

網絡流24題14. 孤島營救問題

2019-11-06 06:40:59
字體:
來源:轉載
供稿:網友

孤島營救問題

Description

1944 年,特種兵麥克接到國防部的命令,要求立即趕赴太平洋上的一個孤島,營救被敵軍俘虜的大兵瑞恩。瑞恩被關押在一個迷宮里,迷宮地形復雜,但幸好麥克得到了迷宮的地形圖。迷宮的外形是一個長方形,其南北方向被劃分為 N 行,東西方向被劃分為 M 列,于是整個迷宮被劃分為 N×M 個單元。每一個單元的位置可用一個有序數對(單元的行號,單元的列號)來表示。南北或東西方向相鄰的 2 個單元之間可能互通,也可能有一扇鎖著的門,或者是一堵不可逾越的墻。迷宮中有一些單元存放著鑰匙,并且所有的門被分成 P 類,打開同一類的門的鑰匙相同,不同類門的鑰匙不同。 大兵瑞恩被關押在迷宮的東南角,即(N,M)單元里,并已經昏迷。迷宮只有一個入口,在西北角。也就是說,麥克可以直接進入(1,1)單元。另外,麥克從一個單元移動到另一個相鄰單元的時間為 1,拿取所在單元的鑰匙的時間以及用鑰匙開門的時間可忽略不計。 試設計一個算法,幫助麥克以最快的方式到達瑞恩所在單元,營救大兵瑞恩。

Input

第 1 行有 3 個整數,分別表示 N,M,P 的值。第 2 行是 1 個整數 K,表示迷宮中門和墻的總數。第 I+2 行(1<=I<=K),有 5 個整數,依次為Xi1,Yi1,Xi2,Yi2,Gi: 當 Gi>=1 時,表示(Xi1,Yi1)單元與(Xi2,Yi2)單元之間有一扇第 Gi 類的門,當 Gi=0 時,表示(Xi1,Yi1)單元與(Xi2,Yi2)單元之間有一堵不可逾越的墻(其中,|Xi1-Xi2|+|Yi1-Yi2|=1,0<=Gi<=P)。 第 K+3 行是一個整數 S,表示迷宮中存放的鑰匙總數。 第 K+3+J 行(1<=J<=S),有 3 個整數,依次為 Xi1,Yi1,Qi:表示第 J 把鑰匙存放在(Xi1,Yi1)單元里,并且第 J 把鑰匙是用來開啟第 Qi 類門的。(其中 1<=Qi<=P)。 輸入數據中同一行各相鄰整數之間用一個空格分隔。

Output

輸出麥克營救到大兵瑞恩的最短時間的值。 如果問題無解,則輸出-1。

Hint

N,M,P <= 10 K < 150

題解

網絡流???喵喵喵??? 分層圖思想。門的數目很小,可以用二進制實現狀態壓縮。而對這2P個狀態可以對應的建2P個圖跑SPFA即可,當然圖不用真的建出來,每次判斷能不能走并在層間轉移即可,具體實現看代碼。

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N = 200, M = 160000, P = 1<<15, inf = 0x3f3f3f3f;const int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};struct Node{ int x, y, z; Node(int a, int b, int c){x = a, y = b, z = c;}};int n, m, p, k, s;int idx[N][N], mp[N][N], inq[N][P], d[N][P], key[N];int ans;void init(){ scanf("%d%d%d%d", &n, &m, &p, &k); int u, v, w; for(int i = 1, t = 0; i <= n; i++) for(int j = 1; j <= m; j++) idx[i][j] = ++t; for(int i = 1; i <= k; i++){ scanf("%d%d", &u, &v); u = idx[u][v]; scanf("%d%d", &v, &w); v = idx[v][w]; scanf("%d", &w); if(!w) mp[u][v] = mp[v][u] = -1; else mp[u][v] = mp[v][u] |= 1 << w; } scanf("%d", &s); for(int i = 1; i <= s; i++){ scanf("%d%d%d", &u, &v, &w); key[idx[u][v]] |= 1 << w; }}void work(){ memset(d, 0x3f, sizeof(d)); d[idx[1][1]][0] = 0; queue<Node> q; q.push(Node(1, 1, 0)); inq[idx[1][1]][0] = 1; while(!q.empty()){ Node u = q.front(); q.pop(); int now = idx[u.x][u.y]; inq[now][u.z] = false; for(int i = 0; i < 4; i++){ int r = u.x + dx[i]; int c = u.y + dy[i]; if(r > 0 && r <= n && c > 0 && c <= m){ int next = idx[r][c]; if(mp[next][now] != -1) if(d[next][u.z] > d[now][u.z] + 1) if((u.z & mp[next][now]) == mp[next][now]){ d[next][u.z|key[next]] = d[next][u.z] = d[now][u.z] + 1; if(!inq[next][u.z|key[next]]){ q.push(Node(r, c, u.z|key[next])); inq[next][u.z|key[next]] = 1; } } } } } ans = inf; for(int i = 0; i < (1<<p+1); i++) ans = min(ans, d[idx[n][m]][i]); if(ans == inf) puts("-1"); else
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 嵩明县| 保亭| 孟津县| 梅河口市| 石泉县| 旺苍县| 江川县| 田东县| 高陵县| 鹤岗市| 诸暨市| 玉山县| 施秉县| 谢通门县| 获嘉县| 陆丰市| 徐汇区| 繁昌县| 余江县| 延安市| 齐齐哈尔市| 大同县| 双桥区| 同仁县| 越西县| 杭锦后旗| 福海县| 福建省| 隆子县| 鄂托克前旗| 子洲县| 洛隆县| 托克逊县| 西林县| 武隆县| 驻马店市| 宜春市| 高州市| 台中县| 肇州县| 蛟河市|