點此看題面
大致題意:有乙個\(n*m\)的四聯通迷宮,相鄰兩個可能互通,可能有一扇門,也可能有一堵牆。對於第\(i\)類的門,你需要有第\(i\)類的鑰匙才可以通過。問你從\((1,1)\)到達\((n,m)\)的最短路。
看到種類數\(≤10\),應該不難想到狀壓吧!而且,我們還可以給每個格仔乙個編號(計算方法:\(pos(x,y)=(x-1)*m+y\))。
我們可以用\(key_i\)來表示編號為\(i\)的格仔上有的鑰匙狀壓之後的結果,並用\(dis_\)來表示從\((1,1)\)出發,到達編號為\(i\)的節點時擁有的鑰匙種類狀壓之後的結果為\(j\)的最短路徑。
接下來,我們可以列舉每乙個節點\(i\)與其乙個相鄰的節點\(j\),然後分類討論:
其中,邊權就相當於走這條邊的條件,一定要當前擁有的鑰匙含有開啟這扇門的鑰匙才行。
建完了圖,就可以開始跑最短路了,當然,這題作為網路流24題之一,你一定要寫網路流也沒人攔你。
一開始初始化擁有的鑰匙狀壓後的結果為1(不然就無法過邊權為1的邊),然後,每到達乙個節點,就可以更新擁有的鑰匙後的狀壓結果了。
最短路的過程應該還是比較簡單的,這題難就難在建圖。
#include#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<0?-(x):(x))
#define ll long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (a==b&&(b=(a=ff)+fread(ff,1,100000,stdin),a==b)?eof:*a++)
#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
#define n 10
#define pos(x,y) ((x-1)*m+y)
#define add(x,y,z) (e[++ee].to=y,e[ee].nxt=lnk[x],e[lnk[x]=ee].val=z)
int pp_=0;char ff[100000],*a=ff,*b=ff,pp[100000];
using namespace std;
int n,m,s,ans=1e9,ee=0,inqueue[n*n+5][1<9) write(x/10);
pc(x%10+'0');
}inline void spfa()//跑最短路
}for(read(t);t;--t) read(x),read(y),read(z),keys[pos(x,y)]|=1
}
洛谷P4011 孤島營救問題(狀壓 BFS)
傳送門 和網路流有半毛錢關係麼 可以發現 n,m,p 都特別小,那麼考慮狀壓,每乙個狀態表示位置以及鑰匙的擁有情況,然後每次因為只能走一步,所以可以用bfs求出最優解 然後是某大佬說的注意點 每個點可以有很多鑰匙,而且初始點也有可能有鑰匙 1 minamoto 2 include3 include4...
狀壓 孤島營救問題
題目鏈結 題目描述 1944 年,特種兵麥克接到國防部的命令,要求立即趕赴太平洋上的乙個孤島,營救被敵軍俘虜的大兵瑞恩。瑞恩被關押在乙個迷宮裡,迷宮地形複雜,但幸好麥克得到了迷宮的地形圖。迷宮的外形是乙個長方形,其南北方向被劃分為 n 行,東西方向被劃分為 m 列,於是整個迷宮被劃分為 n time...
洛谷4011 孤島營救問題(BFS)(狀態壓縮)
1944 年,特種兵麥克接到國防部的命令,要求立即趕赴太平洋上的乙個孤島,營救被敵軍俘虜的大兵瑞恩。瑞恩被關押在乙個迷宮裡,迷宮地形複雜,但幸好麥克得到了迷宮的地形圖。迷宮的外形是乙個長方形,其南北方向被劃分為 n 行,東西方向被劃分為 m 列,於是整個迷宮被劃分為 n m 個單元。每乙個單元的位置...