Jzoj5459【NOIP2017提高A组冲刺11.7】密室
小X 正困在一个密室里,他希望尽快逃出密室。
密室中有N 个房间,初始时,小X 在1 号房间,而出口在N 号房间。
密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条从房间X 到房间Y 的通道。另外,想要通过某个传送门,就必须具备一些种类的钥匙(每种钥匙都要有才能通过)。幸运的是,钥匙在打开传送门的封印后,并不会消失。
然而,通过密室的传送门需要耗费大量的时间,因此,小X 希望通过尽可能少的传送门到达出口,你能告诉小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);
}