JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室
Description
小X 正困在一個密室里,他希望盡快逃出密室。
密室中有N 個房間,初始時,小X 在1 號房間,而出口在N 號房間。
密室的每一個房間中可能有著一些鑰匙和一些傳送門,一個傳送門會單向地創造一條從房間X 到房間Y 的通道。另外,想要通過某個傳送門,就必須具備一些種類的鑰匙(每種鑰匙都要有才能通過)。幸運的是,鑰匙在打開傳送門的封印后,并不會消失。
然而,通過密室的傳送門需要耗費大量的時間,因此,小X 希望通過盡可能少的傳送門到達出口,你能告訴小X 這個數值嗎?
另外,小X 有可能不能逃出這個密室,如果是這樣,請輸出”No Solution”。
Input
第一行三個整數N,M,K,分別表示房間的數量、傳送門的數量以及鑰匙的種類數。
接下來N 行,每行K 個0 或1,若第i 個數為1,則表示該房間內有第i 種鑰匙,若第i 個數為0,則表示該房間內沒有第i 種鑰匙。
接下來M 行,每行先讀入兩個整數X,Y,表示該傳送門是建立在X 號房間,通向Y 號房間的,再讀入K 個0 或1,若第i 個數為1,則表示通過該傳送門需要i 種鑰匙,若第i 個數為0,則表示通過該傳送門不需要第i 種鑰匙。
Output
輸出一行一個“No Solution”,或一個整數,表示最少通過的傳送門數。
Sample Input
3 3 2
1 0
0 1
0 0
1 3 1 1
1 2 1 0
2 3 1 1
Sample Output
2
Data Constraint
Solution
看到 k≤10 ,就想到狀壓DP——二進制狀態!
于是考慮從起點開始做一遍SPFA,用一個二維狀態存即可(位置和狀態)。
但由于邊權為 1 ,沒有松弛操作,所以只需 BFS 一遍,輸出終點答案即可。
Code
#include<cstdio> #include<cstring> using namespace std; const int N=6001; struct data {int x,y; }q[N*1000]; int tot,ans=1e9; int first[N],next[N],en[N],w[N]; int a[N],dis[N][1025]; inline int read() {int X=0,w=1; char ch=0;while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*w; } inline int min(int x,int y) {return x<y?x:y; } inline void insert(int x,int y,int z) {next[++tot]=first[x];first[x]=tot;en[tot]=y;w[tot]=z; } int main() {int n=read(),m=read(),k=read();for(int i=1;i<=n;i++)for(int j=0;j<k;j++) a[i]+=read()<<j;for(int i=1;i<=m;i++){int x=read(),y=read(),z=0;for(int j=0;j<k;j++) z+=read()<<j;insert(x,y,z);}memset(dis,60,sizeof(dis));int l=dis[1][a[1]]=0,r=1;q[1].x=1,q[1].y=a[1];while(l<r){data now=q[++l],t;for(int i=first[now.x];i;i=next[i])if((now.y&w[i])==w[i] && dis[now.x][now.y]+1<dis[en[i]][now.y|a[en[i]]]){dis[en[i]][now.y|a[en[i]]]=dis[now.x][now.y]+1;if(en[i]==n) ans=min(ans,dis[en[i]][now.y|a[en[i]]]);t.x=en[i],t.y=now.y|a[en[i]];q[++r]=t;}}if(ans==1e9) puts("No Solution"); else printf("%d",ans);return 0; }總結
以上是生活随笔為你收集整理的JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 5458. 【NOIP2017
- 下一篇: JZOJ 5460. 【NOIP2017