P4011 孤島營救問題

2022-05-05 14:15:08 字數 2123 閱讀 3613

p4011 孤島營救問題

輸入

449

9121

3212

2202

1220

2131

0233

3024

3413

2330

3343

0434

4022

1242

1

輸出

14
(原題太長我就不貼了,簡單敘述一下)

乙個n*m的迷宮,每個單元格之間可能有門或者牆,也可能啥也沒有。門和牆的總數為k(會讀入牆和門的位置座標)

門存在種類,只有擁有對應種類的鑰匙才可以開啟這類門

鑰匙的總量為s(會讀入鑰匙的座標)

從乙個單元格到另乙個單元格時間為1

現在從左上角(1,1)出發,到右下角(n,m),最少花費多少時間?

針對樣例,看圖分析

紫色為鑰匙

橙色為牆或者門的種類

綠色為線路

這就是網路流嗎?愛了愛了

迷宮的題一般用bfs就可以做

有了鑰匙我們就狀壓+bfs

狀態壓縮鑰匙,是為了方便記錄每一把鑰匙的狀態

就比如當前狀態是「100」,說明我有第三把鑰匙,因為第三位(從右往左)是1,而「100」對應的是4,你會發現你擁有第i把鑰匙,狀態就是2i-1(十進位制下),這樣我們就可以用二進位制來儲存鑰匙資訊

key|=key [ x ] [ y ] //就是將當前已有鑰匙的狀態給key

我們在開門時驗證自己有鑰匙的方式:

( mp [x] [y] [u.x] [u.y] & key ) ! = mp [x] [y] [u.x] [u.y]

[x][y]表示當前單元格,[u.x][u.y]表示上乙個單元格

mp就表示兩個單元格之間門的編號,也可能是牆(表示方式和鑰匙一樣),直接與鑰匙&運算,如果運算後還是本身,說明有指定的鑰匙(因為有鑰匙說明那一位為1,1&1=1,還是本身,如果沒有指定鑰匙,說明那一位是0,0&1=0,值就發生改變)

然後就是bfs的走迷宮過程,走迷宮有四種狀態要continue

1.如果超格仔了

2.如果撞牆了

3.如果遇到門但是木有鑰匙

4.之前走過了

坑點:1.鑰匙可以重複使用而非用過即毀

2.乙個地方可以存放多個鑰匙,所以儲存鑰匙時不要將前乙個覆蓋掉

3.初始點也可以放鑰匙

4.存在走不通的情況記得輸出-1

**中注釋非常詳細

#include

using

namespace std;

const

int dx=

;//增量陣列

const

int dy=

;int vis[25]

[25][

40005

],x,y,xx,yy,p,pw[

105]

,mp[16]

[16][

16][16

],key[20]

[20],n,m,tot;

struct nodq[

5000005];

//q為廣蒐用的佇列

intbfs()

;for

(;h<=t;

++h)

;//儲存當前座標,以及鑰匙與步伐情況

if(x==n&&y==m)

return stp;

//如果已經走到(n,m)則返回答案}}

return-1

;//無法抵達

}int

main()

else

}int q;

scanf

("%d"

,&tot)

;while

(tot--

) cout<<

bfs();

return0;

}

這個題我就用兩個字形容:絕了

很久沒有遇到這麼好的題

P4011 孤島營救問題

1944 年,特種兵麥克接到國防部的命令,要求立即趕赴太平洋上的乙個孤島,營救被敵軍俘虜的大兵瑞恩。瑞恩被關押在乙個迷宮裡,迷宮地形複雜,但幸好麥克得到了迷宮的地形圖。迷宮的外形是乙個長方形,其南北方向被劃分為 n 行,東西方向被劃分為 m 列,於是整個迷宮被劃分為 n times m 個單元。每乙...

洛谷P4011 孤島營救問題(狀壓 BFS)

傳送門 和網路流有半毛錢關係麼 可以發現 n,m,p 都特別小,那麼考慮狀壓,每乙個狀態表示位置以及鑰匙的擁有情況,然後每次因為只能走一步,所以可以用bfs求出最優解 然後是某大佬說的注意點 每個點可以有很多鑰匙,而且初始點也有可能有鑰匙 1 minamoto 2 include3 include4...

洛谷4011 孤島營救問題(BFS)(狀態壓縮)

1944 年,特種兵麥克接到國防部的命令,要求立即趕赴太平洋上的乙個孤島,營救被敵軍俘虜的大兵瑞恩。瑞恩被關押在乙個迷宮裡,迷宮地形複雜,但幸好麥克得到了迷宮的地形圖。迷宮的外形是乙個長方形,其南北方向被劃分為 n 行,東西方向被劃分為 m 列,於是整個迷宮被劃分為 n m 個單元。每乙個單元的位置...