拯救大兵瑞恩
题目描述:
n * m的地图,有p类门,当然对应的就有p类钥匙可以开对应的门,拿到对应门的钥匙才能开对应的门,门是双开门,还有若干个不可逾越的墙,你现在在
(1, 1)
,你要去到(n, m)
,问最短路程
思路:
一看这个题就很难写,本来是不想写的,后来静下心来看了看,感觉也不是特别难写,就顺手写了
我的整体思路是将二维地图压缩成一维,然后跑BFS,bfs的队列塞的是一个结构体,结构体里面有三个参数,当前点对应的一维的坐标、走过的距离、拿到的钥匙,前两个是
int
型,第三个是bitse
,因为他可以下标访问还可以进行或操作写了两个函数:将二维坐标转换成一维坐标的
getid
、将一维坐标转换成二维坐标getpii
用一个二维数组来处理输入的两个点之间的关系,初始化为-1,再根据输入的来修改,最后-1表示可以通行,0表示是墙不可通行,x表示是一个有x锁的门,需要有钥匙x才能通行
对于输入的钥匙,因为每个位置可能有多个钥匙,所以我开了一个biset数组,将点的二维压成一维后存他的钥匙
BFS的时候,先初始化一号点,特别是要初始化一号点的初始钥匙,更新的时候先判断是否出界,再判断是否是墙,或者有没有能开门的钥匙,能到达对应点的时候就更新当前状态对应的钥匙,塞进队列
记得开一个二维的vis数组,第一维存压缩过的第一维,第二维存当前状态的钥匙,这里可以用
bitset
的一个转换成无符号整数的函数来搞
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod 1000000007
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define y1 y114514
typedef long long ll;
typedef pair <int,int> pii;
#define MAX 300000 + 50
int n, m, k, p;
int x1, x2, y1, y2, g;
int tr[150][150];
bitset<30>key[205];
bool vis[300][300];
int getid(int x, int y){
return (x - 1) * m + y;
}
pii getpii(int p){
return m_p((p + m - 1) / m, ((p - 1) % m) + 1);
}
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
struct ran{
int u, d;
bitset<30>fuck;
};
bool judge(int x, int y){
if(x > n || x < 1 || y > m || y < 1)return false;
return true;
}
void bfs(){
queue<ran>q;
bitset<30>f = 0;
f |= key[1];
q.push({1, 0, f});
while (!q.empty()) {
auto [u, d, fuck] = q.front();q.pop();
if(vis[u][fuck.to_ulong()])continue;
vis[u][fuck.to_ulong()] = 1;
if(u == n * m){
cout << d << endl;
return;
}
auto [x, y] = getpii(u);
for(int i = 0; i < 4; ++i){
int xx = x + dx[i];
int yy = y + dy[i];
int p = tr[getid(x, y)][getid(xx, yy)];
if(p == 0 || !judge(xx, yy))continue;
if(p == -1 || (p != -1 && fuck[p])){
bitset<30>fuckk = fuck;
fuckk |= key[getid(xx, yy)];
q.push({getid(xx, yy), d + 1, fuckk});
}
}
}
cout << -1 << endl;
}
void work(){
cin >> n >> m >> p >> k;
mem(tr, -1);
while (k--) {
cin >> x1 >> y1 >> x2 >> y2 >> g;
tr[getid(x1, y1)][getid(x2, y2)] = g;
tr[getid(x2, y2)][getid(x1, y1)] = g;
}
cin >> k;
while (k--) {
cin >> x1 >> y1 >> g;
key[getid(x1, y1)][g] = 1;
}
bfs();
}
int main(){
io;
work();
return 0;
}