5459. 【NOIP2017提高A组冲刺11.7】密室 
(File IO): input:room.in output:room.out

Time Limits: 1000 ms  Memory Limits: 524288 KB  Detailed Limits  

Goto ProblemSet

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][], ls[N];
int mi[], tot;
struct edge
{
int to, next, pre;
}e[N * ];
int list[N * ][]; 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 = ; i <= n; i++)
{
int x;
pre[i] = ;
for (int j = ; j <= k; j++)
{
scanf("%d", &x);
pre[i] += x * mi[j];
}
} for (int i = ; i <= m; i++)
{
int x, y, z;
scanf("%d%d", &x, &y);
int p = ;
for (int j = ; j <= k; j++)
scanf("%d", &z), p += mi[j] * z;
add(x, y, p);
}
} void pre_work()
{
mi[] = ;
for (int i = ; i <= ; i++)
mi[i] = mi[i - ] * ; } void work()
{
memset(dis, 0x7f7f7f7f, sizeof(dis));
dis[][pre[]] = ;
list[][] = ;
list[][] = pre[];
int head = , tail = ;
while (head < tail)
{
head++;
int now = list[head][];
int p = list[head][];
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] + ;
list[++tail][] = e[i].to;
list[tail][] = net;
}
}
}
int ans = 0x7f7f7f7f;
for (int i = ; i <= mi[k + ] - ; 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();
}
05-23 17:24