计蒜客 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的密室