计蒜客 2017 NOIP 提高组模拟赛Day1 T2 小X的密室

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜客 2017 NOIP 提高组模拟赛Day1 T2 小X的密室相关的知识,希望对你有一定的参考价值。

https://nanti.jisuanke.com/t/17323

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

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

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

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

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

输入格式

第一行三个整数 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种钥匙。

输出格式

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

技术分享

思路:

一道很有意思的搜索题,如果没有钥匙存在的话,那么这道题就变成一道纯粹的搜索题了。

在有钥匙存在的情况下,那么思考用什么来表示钥匙的状态最为方便。。。那显然是二进制了,每一次钥匙状态的判断可以用与运算解决,钥匙的传递可以用或运算解决,非常方便而且复杂度极低。

具体看代码以及最后一组测试点没有过(大雾

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <queue>
  4 #include <vector>
  5 using namespace std;
  6 
  7 int dis[6005];
  8 bool vis[6005];
  9 int key[6005];
 10 
 11 int n,m,k;
 12 
 13 struct edge
 14 {
 15     int from,to;
 16     int cost;
 17 };
 18 
 19 vector<edge> edges;
 20 vector<int> v[6005];
 21 
 22 void adde(int from,edge tmp)
 23 {
 24     edges.push_back(tmp);
 25 
 26     int m = edges.size();
 27 
 28     v[from].push_back(m-1);
 29 }
 30 
 31 void bfs1(void)
 32 {
 33     vis[1] = 1;
 34 
 35     queue<int> q;
 36 
 37     q.push(1);
 38 
 39     bool f = 0;
 40 
 41     while (!q.empty())
 42     {
 43         int s = q.front();q.pop();
 44 
 45         for (int i = 0;i < v[s].size();i++)
 46         {
 47             int j = v[s][i];
 48 
 49             int to = edges[j].to;
 50 
 51             if (vis[to]) continue;
 52 
 53             vis[to] = 1;
 54 
 55             dis[to] = dis[s] + 1;
 56 
 57             q.push(to);
 58 
 59             if (to == n)
 60             {
 61                 f = 1;
 62                 break;
 63             }
 64         }
 65 
 66         if (f) break;
 67     }
 68 }
 69 
 70 void bfs2()
 71 {
 72     vis[1] = 1;
 73 
 74     queue<int> q;
 75 
 76     q.push(1);
 77 
 78     bool f = 0;
 79 
 80     while (!q.empty())
 81     {
 82         int s = q.front();q.pop();
 83 
 84         for (int i = 0;i < v[s].size();i++)
 85         {
 86             int j = v[s][i];
 87 
 88             int to = edges[j].to;
 89 
 90             int w = edges[j].cost;
 91 
 92             if (vis[to]) continue;
 93 
 94             if ((key[s] & w) < w) continue;
 95 
 96             key[to] |= w;
 97             key[to] |= key[s];
 98 
 99             vis[to] = 1;
100 
101             dis[to] = dis[s] + 1;
102 
103             q.push(to);
104 
105             if (to == n)
106             {
107                 f = 1;
108                 break;
109             }
110         }
111 
112         if (f) break;
113     }
114 }
115 
116 int main()
117 {
118     scanf("%d%d%d",&n,&m,&k);
119 
120     if (!k)
121     {
122         for (int i = 0;i < m;i++)
123         {
124             int x,y;
125 
126             scanf("%d%d",&x,&y);
127 
128             edge tmp = (edge){x,y,1};
129 
130             adde(x,tmp);
131         }
132 
133         bfs1();
134 
135         if (!vis[n]) printf("No Solution\n");
136         else printf("%d\n",dis[n]);
137     }
138     else
139     {
140         for (int i = 1;i <= n;i++)
141         {
142             int tmp = 0;
143 
144             for (int j = 1;j <= k;j++)
145             {
146                 int x;
147 
148                 scanf("%d",&x);
149 
150                 if (x) tmp = tmp | (1 << j);
151             }
152 
153             key[i] = tmp;
154         }
155 
156         for (int i = 1;i <= m;i++)
157         {
158             int x,y;
159 
160             scanf("%d%d",&x,&y);
161 
162             int tmp = 0;
163 
164             for (int j = 1;j <= k;j++)
165             {
166                 int x;
167 
168                 scanf("%d",&x);
169 
170                 if (x) tmp = tmp | (1 << j);
171             }
172 
173             edge e = (edge){x,y,tmp};
174 
175             adde(x,e);
176         }
177 
178         bfs2();
179 
180         if (!vis[n]) printf("No Solution\n");
181         else printf("%d\n",dis[n]);
182     }
183 
184     return 0;
185 }

 

以上是关于计蒜客 2017 NOIP 提高组模拟赛Day1 T2 小X的密室的主要内容,如果未能解决你的问题,请参考以下文章

计蒜客 2017 NOIP 提高组模拟赛Day1 T2 小X的密室

计蒜客 2017 NOIP 提高组模拟赛Day1 T1 小X的质数 线性筛素数

计蒜客NOIP2017提高组模拟赛day2-小区划分

计蒜客NOIP2017提高组模拟赛day2-直线的交点

计蒜客2017.9.9 Day1 NOIP模拟赛

计蒜客NOIP2017提高组模拟赛day2-数三角形