计蒜客NOIP模拟赛4 D1T2小X的密室

小 X 正困在一个密室里,他希望尽快逃出密室。

密室中有 N 个房间,初始时,小 X 在 1 号房间,而出口在 N 号房间。

密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条从房间 X 到房间 Y 的通道。另外,想要通过某个传送门,就必须具备一些种类的钥匙(每种钥匙都要有才能通过)。幸运的是,钥匙在打开传送门的封印后,并不会消失。

然而,通过密室的传送门需要耗费大量的时间,因此,小 X 希望通过尽可能少的传送门到达出口,你能告诉小 X 这个数值吗?

另外,小 X 有可能不能逃出这个密室,如果是这样,请输出 "No Solution"

输入格式

第一行三个整数 N,M,K,分别表示房间的数量、传送门的数量以及钥匙的种类数。

接下来 N 行,每行 K01,若第 i 个数为 1,则表示该房间内有第 i种钥匙,若第 i 个数为 0,则表示该房间内没有第 i种钥匙。

接下来 M 行,每行先读入两个整数 X,Y,表示该传送门是建立在 X号房间,通向 Y 号房间的,再读入 K01,若第 i 个数为 1,则表示通过该传送门需要 i 种钥匙,若第 i 个数为 0,则表示通过该传送门不需要第 iii 种钥匙。

输出格式

输出一行一个 "No Solution",或一个整数,表示最少通过的传送门数。

数据规模与约定

样例输入1

3 3 2
1 0
0 1
0 0
1 3 1 1
1 2 1 0
2 3 1 1

样例输出1

2

样例输入2

20 40 0
10 18 
18 14 
19 13 
4 14 
13 10 
5 18 
14 1 
13 13 
10 16 
19 11 
11 15 
10 18 
5 8 
12 19 
7 8 
18 6 
14 5 
9 5 
2 17 
13 14 
18 15 
8 18 
7 1 
13 5 
4 6 
17 4 
1 4 
10 10 
13 8 
19 2 
4 9 
3 3 
5 10 
17 5 
12 8 
19 11 
3 16 
17 10 
18 16 
13 13 

样例输出2

No Solution

样例输入3

20 50 0
8 10 
7 17 
5 11 
14 20 
20 16 
8 19 
12 11 
18 7 
17 5 
4 15 
16 11 
11 8 
10 12 
8 9 
16 8 
3 16 
1 6 
3 20 
6 10 
11 12 
6 8 
18 17 
14 17 
3 11 
4 19 
9 2 
8 6 
13 2 
5 2 
12 19 
8 10 
14 7 
6 12 
6 4 
13 2 
8 7 
13 19 
17 9 
3 14 
18 20 
2 14 
4 17 
20 15 
14 15 
2 15 
7 20 
12 12 
18 10 
15 9 
15 9 

样例输出3

4

裸的搜索
把钥匙的状态压缩为二进制数x<1024
判断能否传送?
边权为需要钥匙的状态
dis&x==dis那么就可以传送
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 struct Node
 8 {
 9     int next,to,dis;
10 }edge[50001];
11 struct zt
12 {
13     int x,t;
14 };
15 int num,head[5001];
16 int dist[5001][1501],key[5001],n,k,m;
17 bool vis[5001][1501];
18 void add(int u,int v,int dis)
19 {
20     num++;
21     edge[num].next=head[u];
22     head[u]=num;
23     edge[num].to=v;
24     edge[num].dis=dis;
25 }
26 void SPFA()
27 {int i;
28     queue<zt> Q;
29     memset(dist,127/3,sizeof(dist));
30     Q.push((zt){1,key[1]});
31     dist[1][key[1]]=0;
32    while (Q.empty()==0)
33     {
34        zt u=Q.front();
35        Q.pop();
36        vis[u.x][u.t]=0;
37          for (i=head[u.x];i;i=edge[i].next)
38          {
39              int v=edge[i].to;
40              if ((edge[i].dis&u.t)==edge[i].dis&&dist[v][u.t|key[v]]>dist[u.x][u.t]+1)
41              {
42                  dist[v][u.t|key[v]]=dist[u.x][u.t]+1;
43                  if (v==n)
44                  {
45                      cout<<dist[v][u.t|key[v]];
46                      return;
47                  }
48                  if (vis[v][u.t|key[v]]==0)
49                  {
50                      vis[v][u.t|key[v]]=1;
51                      Q.push((zt){v,u.t|key[v]});
52                  }
53              }
54          }
55     }
56     cout<<"No Solution";
57     return;
58 }
59 int main()
60 {int i,j,x,l,r;
61     cin>>n>>m>>k;
62     for (i=1;i<=n;i++)
63     {
64         for (j=1;j<=k;j++)
65         {scanf("%d",&x);
66             if (x) key[i]|=(1<<j-1);
67         }
68     }
69     for (i=1;i<=m;i++)
70     {
71         scanf("%d%d",&l,&r);
72         int dis=0;
73         for (j=1;j<=k;j++)
74         {scanf("%d",&x);
75             if (x) dis|=(1<<j-1);
76         }
77         add(l,r,dis);
78     }    
79     SPFA();
80 }
原文地址:https://www.cnblogs.com/Y-E-T-I/p/7588234.html