这题目标是通过移动拿到所有钥匙,上锁的房间需要对应的钥匙,思路是通过|和&二进制判断是否有对应钥匙,与普通不同的是,不同点是当我重复进入一个房间时,不能单纯通过有无来过来判断是否continue,而是要通过进入这个房间时钥匙的状况来判断
点击查看代码
struct node {
int x, y, w;// 代表在x,y位置时有w个钥匙
};
queue<node> q;
int d[6] = {-1, 0, 1, 0};
int d1[6]={0,1,0,-1}// fangxiang
int vis[200][200][13];
memset(vis,0,sizeof(0));
int key = 0;
int n = a.size(), m = a[0].size();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (a[i][j] == '@') {//代表起点,入队
q.push({i, j, 0});
}
if (a[i][j] >= 'a' && a[i][j] <= 'f') {
key |= 1 << (a[i][j] - 'a');//,小写是钥匙更新钥匙的状态,说明最终要获得多少个钥匙;
}
}
}
int s = 0;
while (q.size()) {
for (int i = 0; i < q.size(); i++) {
node from= q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int x1 = from.x + d[i];
int y1 = from.y + d1[i];
if (x1>=0 && x1 < n &&y1 >= 0 &&y1 < m) {
char c = a[x1][y1];
int w1 = from.w;
if (c == '#') {//撞墙跳过
continue;
}
if (c >= 'a' && c <= 'f') {//小写是钥匙 ,w1是当前钥匙总数
w1 |= (1 << (c - 'a'));
}
if (c >= 'A' && c <= 'F') {
if ((w1 & (1 << (c - 'A'))) == 0) {//大写是锁,&有一出一,1和1碰到就代表当前有需要能开锁的钥匙
continue;
}
}
if (w1 == key) {//如果所有的钥匙都有,直接返回当钱层数
return s + 1;
}
if (!vis[x1][y1][w1]) {//如果没在当前钥匙状态下访问过当前节点,入队
vis[x1][y1][w1] = 1;
q.push({x1, y1, w1});
}
}
}
}
s++;//增加层数,如果放for会不知道是哪一层,层数会多;
}
return -1;//无法获得所有钥匙就返回