[JZOJ5459]【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


 


 

 

话说这题很眼熟啊...

直接状压一发,然后跑一个bfs。

其实是码农题, 此题一A没有调试真的是特别爽。

 


 

 

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
inline int read() {
    int res=0;char c=getchar();bool f=0;
    while(!isdigit(c)) {if(c=='-')f=1;c=getchar();}
    while(isdigit(c))res=(res<<3)+(res<<1)+(c^48),c=getchar();
    return f?-res:res;
}

int n, m, k;
struct edge{
    int nxt, to, sit;
}ed[6006];
int head[5005], cnt;
inline void add(int x, int y, int z)
{
    ed[++cnt] = (edge){head[x], y, z, };
    head[x] = cnt;
}
int w[5005]; 
struct date {
    int x, sit;
};
int dis[1<<11][5005];

int main()
{
    freopen("room.in", "r", stdin);
    freopen("room.out", "w", stdout);    
    n = read(), m = read(), k = read();
    for (int i = 1; i <= n; i ++)
    {
        int x = 0;
        for (int j = 1 ; j <= k ; j ++)
        {
            x <<= 1;
            x |= read();
        }
        w[i] = x;
    }
    
    for (int i = 1 ; i <= m ; i ++)
    {
        int x = read(), y = read();
        int re = 0;
        for (int j = 1 ; j <= k ; j ++)
        {
            re <<= 1;
            re |= read();
        }
        add(x, y, re);
    }
    queue <date> q;
    memset(dis, -1, sizeof dis);
    q.push((date){1, w[1]});
    dis[w[1]][1] = 0;
    while(!q.empty())
    {
        int x = q.front().x, so = q.front().sit;
        q.pop();
        for (int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if ((so & ed[i].sit) == ed[i].sit and dis[so|w[to]][to] == -1)
            {
                dis[so|w[to]][to] = dis[so][x] + 1;
                q.push((date){to, so | w[to]});
            }
        }
    }
    int ans = 1e9;
    for (int i = 0 ; i <= (1 << k) - 1 ; i ++) if (dis[i][n] != -1)ans = min(ans, dis[i][n]);
    if (ans == 1e9) return puts("No Solution"), 0;
    printf("%d\n", ans);
    return 0;
}

 

posted @ 2018-08-14 19:14  zZhBr  阅读(248)  评论(0编辑  收藏  举报