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 個單元。每乙個單元的位置...