JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室

9 篇文章 0 订阅
2 篇文章 0 订阅

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

Data Constraint

Solution

  • 看到 k10 ,就想到状压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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值