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


 
做法: 将K状态压缩后直接bfs即可
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#define N 5007
using namespace std;
int n, m, k, pre[N], dis[N][1300], ls[N];
int mi[30], tot;
struct edge
{
    int to, next, pre;
}e[N * 2];
int list[N * 3330][2];

void add(int x, int y, int z)
{
    e[++tot].to = y;
    e[tot].next = ls[x];
    e[tot].pre = z;
    ls[x] = tot;
}

void init()
{
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= n; i++)
    {
        int x;
        pre[i] = 0;
        for (int j = 1; j <= k; j++)
        {
            scanf("%d", &x);
            pre[i] += x * mi[j];
        }
    }
    
    for (int i = 1; i <= m; i++)
    {
        int x, y, z;
        scanf("%d%d", &x, &y);
        int p = 0;
        for (int j = 1; j <= k; j++)
            scanf("%d", &z), p += mi[j] * z; 
        add(x, y, p);
    }
}

void pre_work()
{
    mi[1] = 1;
    for (int i = 2; i <= 12; i++)
        mi[i] = mi[i - 1] * 2;
    
} 

void work()
{
    memset(dis, 0x7f7f7f7f, sizeof(dis));
    dis[1][pre[1]] = 0;
    list[1][0] = 1;
    list[1][1] = pre[1];
    int head = 0, tail = 1;
    while (head < tail)
    {
        head++;
        int now = list[head][0];
        int p = list[head][1];
        for (int i = ls[now]; i; i = e[i].next)
        {
            if ((p | e[i].pre) != p)    continue;
            int net = p | pre[e[i].to];
            if (dis[e[i].to][net] == 0x7f7f7f7f)
            {
                dis[e[i].to][net] = dis[now][p] + 1;
                list[++tail][0] = e[i].to;
                list[tail][1] = net;    
            }    
        }
    }
    int ans = 0x7f7f7f7f;
    for (int i = 0; i <= mi[k + 1] - 1; i++)
        ans = min(ans, dis[n][i]);
    if (ans != 0x7f7f7f7f)    printf("%d", ans);
    else printf("No Solution");
}

int main()
{
    //freopen("room.in", "r", stdin);
    //freopen("room.out", "w", stdout);
    pre_work();
    init();    
    work();
}

猜你喜欢

转载自www.cnblogs.com/traveller-ly/p/9439740.html