Jzoj5459【NOIP2017提高A組衝刺11.7】密室

weixin_30639719發表於2020-04-05
小X 正困在一個密室裡,他希望儘快逃出密室。
密室中有N 個房間,初始時,小X 在1 號房間,而出口在N 號房間。
密室的每一個房間中可能有著一些鑰匙和一些傳送門,一個傳送門會單向地創造一條從房間X 到房間Y 的通道。另外,想要通過某個傳送門,就必須具備一些種類的鑰匙(每種鑰匙都要有才能通過)。幸運的是,鑰匙在開啟傳送門的封印後,並不會消失。
然而,通過密室的傳送門需要耗費大量的時間,因此,小X 希望通過儘可能少的傳送門到達出口,你能告訴小X 這個數值嗎?

另外,小X 有可能不能逃出這個密室,如果是這樣,請輸出"No Solution"。

一開始以為是一個搜尋果斷跳,結果看到資料範圍發現可以做

發現k很小,這就是一個傻逼狀壓分層圖啊

而且還不帶邊權的,直接bfs,dijk都不用了

#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct nod{ int x,k; } c;
struct edge{ int v,c,nt; }G[10010];
queue<nod> q;
int d[1110][5010],w[5010],h[5010];
int n,m,k,cnt=0,ans=1<<30;
inline void adj(int x,int y,int c){
	G[++cnt]=(edge){y,c,h[x]}; h[x]=cnt;
}
inline int get(){
	int s=0;
	for(int x,i=0;i<k;++i) scanf("%d",&x),s|=x<<i;
	return s;
}
int main(){
	freopen("room.in","r",stdin);
	freopen("room.out","w",stdout);
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;++i) w[i]=get();
	for(int x,y,i=1;i<=m;++i){
		scanf("%d%d",&x,&y);
		adj(x,y,get());
	}
	memset(d,-1,sizeof d);
	d[w[1]][1]=0; q.push((nod){1,w[1]});
	for(int x,y;!q.empty();q.pop()){
		c=q.front(); x=c.x; y=c.k; 
		for(int v,i=h[x];i;i=G[i].nt)
			if(((y&G[i].c)==G[i].c)&&d[y|w[G[i].v]][v=G[i].v]==-1){
				d[y|w[v]][v]=d[y][x]+1; q.push((nod){v,y|w[v]});
			}
	}
	for(int i=0;i<(1<<k);++i) if(~d[i][n]) ans=min(ans,d[i][n]);
	if(ans==1<<30) puts("No Solution"); else printf("%d\n",ans);
}

轉載於:https://www.cnblogs.com/Extended-Ash/p/7800594.html